TL;DR: Use
#require
in Swift Tests for critical conditions; it unwraps optionals, mandatestry
, and halts tests on failure. Choose#expect
for non-critical assertions that allow test execution to continue after failure.
In the Swift Testing framework, #expect
and #require
are common assertion macros. While they serve similar purposes, they differ significantly in behavior and use cases.
Key Differences
1. Usage of try
#require
mandates the use of try
regardless of whether the Boolean expression might throw an error.
Example:
Swift
@Test func person() throws {
let person = Person(name: "Fat", age: 10)
try #require(person.age == 10) // Must use `try`
#expect(person.name == "Fat") // No `try` needed
}
2. Optional Unwrapping
#require
can directly unwrap optional values (similar to XCTUnwrap
). If unwrapping fails, the test automatically fails.
Example:
Swift
@Test func notOptional() throws {
let person: Person? = Person(name: "Fat", age: 10)
let unwrappedPerson = try #require(person) // Successfully unwrapped
#expect(unwrappedPerson.name == "Fat")
}
3. Behavior on Assertion Failure
#expect
- Behavior: Even if the assertion fails, the test case continues executing subsequent lines.
- Example:
Swift
@Test func example() async throws {
#expect(3 < 0) // Assertion fails
print("next line") // Still executes
}
Output:
◇ Test run started.
✘ Expectation failed: 3 < 0
↳ next line
✘ Test example() failed after 0.001 seconds with 1 issue.
#require
- Behavior: If the assertion fails, the test case terminates immediately, and subsequent lines are not executed.
- Example:
Swift
@Test func example() async throws {
try #require(3 < 0) // Assertion fails and halts execution
print("next line") // Does not execute
}
Output:
◇ Test run started.
✘ Expectation failed: 3 < 0
✘ Test example() failed after 0.002 seconds with 1 issue.
Summary
#expect
: Use for non-critical assertions where test execution should proceed even after a failure.#require
: Use for critical conditions that must be met; failure terminates the test case.