🔍 Choose Between #expect and #require in Swift Tests

Get weekly handpicked updates on Swift and SwiftUI!

TL;DR: Use #require in Swift Tests for critical conditions; it unwraps optionals, mandates try, 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.

Further Reading