Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tkersey/c277d94c3f33842460c102b95f72d7cf to your computer and use it in GitHub Desktop.
Save tkersey/c277d94c3f33842460c102b95f72d7cf to your computer and use it in GitHub Desktop.
The Ultimate Swift Testing Playbook (feed it your agents for better tests!)

The Ultimate Swift Testing Playbook (2024 WWDC Edition, expanded with Apple docs from June 2025)

Updated with info from https://developer.apple.com/documentation/testing fetched via Firecrawl on June 7, 2025.

A hands-on, comprehensive guide for migrating from XCTest to Swift Testing and mastering the new framework. This playbook integrates the latest patterns and best practices from WWDC 2024 and official Apple documentation to make your tests more powerful, expressive, and maintainable.


1. Migration & Tooling Baseline

Ensure your environment is set up for a smooth, gradual migration.

What Why
Xcode 16 & Swift 6 Swift Testing is bundled with the latest toolchain. It leverages modern Swift features like macros, structured concurrency, and powerful type-system checks.
Keep XCTest Targets Incremental Migration is Key. You can have XCTest and Swift Testing tests in the same target, allowing you to migrate file-by-file without breaking CI. Both frameworks can coexist.
Enable Parallel Execution In your Test Plan, ensure "Use parallel execution" is enabled. Swift Testing runs tests in parallel by default, which dramatically speeds up test runs and helps surface hidden state dependencies that serial execution might miss.

Migration Action Items

  • Ensure all developer machines and CI runners are on macOS 15+ and Xcode 16+.
  • For projects supporting Linux/Windows, add the swift-testing SPM package to your Package.swift. It's bundled in Xcode and not needed for Apple platforms.
  • For existing test targets, you must explicitly enable the framework. In the target's Build Settings, find Enable Testing Frameworks and set its value to Yes. Without this, import Testing will fail.
  • In your primary test plan, confirm that “Use parallel execution” is enabled. This is the default and recommended setting.

2. Expressive Assertions: #expect & #require

Replace the entire XCTAssert family with two powerful, expressive macros. They accept regular Swift expressions, eliminating the need for dozens of specialized XCTAssert functions.

Macro Use Case & Behavior
#expect(expression) Soft Check. Use for most validations. If the expression is false, the issue is recorded, but the test function continues executing. This allows you to find multiple failures in a single run.
#require(expression) Hard Check. Use for critical preconditions (e.g., unwrapping an optional). If the expression is false or throws, the test is immediately aborted. This prevents cascading failures from an invalid state.

Power Move: Visual Failure Diagnostics

Unlike XCTAssert, which often only reports that a comparison failed, #expect shows you the exact values that caused the failure, directly in the IDE and logs. This visual feedback is a massive productivity boost.

Code:

@Test("User count meets minimum requirement")
func testUserCount() {
    let userCount = 5
    // This check will fail
    #expect(userCount > 10)
}

Failure Output in Xcode:

▽ Expected expression to be true
#expect(userCount > 10)
      |         | |
      5         | 10
                false

Power Move: Optional-Safe Unwrapping

#require is the new, safer replacement for XCTUnwrap. It not only checks for nil but also unwraps the value for subsequent use.

Before: The XCTest Way

// In an XCTestCase subclass...
func testFetchUser_XCTest() async throws {
    let user = try XCTUnwrap(await fetchUser(id: "123"), "Fetching user should not return nil")
    XCTAssertEqual(user.id, "123")
}

After: The Swift Testing Way

@Test("Fetching a valid user succeeds")
func testFetchUser() async throws {
    // #require both checks for nil and unwraps `user` in one step.
    // If fetchUser returns nil, the test stops here and fails.
    let user = try #require(await fetchUser(id: "123"))

    // `user` is now a non-optional User, ready for further assertions.
    #expect(user.id == "123")
    #expect(user.age == 37)
}

Common Assertion Conversions Quick-Reference

Use this table as a cheat sheet when migrating your XCTest assertions.

XCTest Assertion Swift Testing Equivalent Notes
XCTAssert(expr) #expect(expr) Direct replacement for a boolean expression.
XCTAssertEqual(a, b) #expect(a == b) Use the standard == operator.
XCTAssertNotEqual(a, b) #expect(a != b) Use the standard != operator.
XCTAssertNil(a) #expect(a == nil) Direct comparison to nil.
XCTAssertNotNil(a) #expect(a != nil) Direct comparison to nil.
XCTAssertTrue(a) #expect(a) No change needed if a is already a Bool.
XCTAssertFalse(a) #expect(!a) Use the ! operator to negate the expression.
XCTAssertGreaterThan(a, b) #expect(a > b) Use any standard comparison operator: >, <, >=, <=
try XCTUnwrap(a) try #require(a) The preferred, safer way to unwrap optionals.
XCTAssertThrowsError(expr) #expect(throws: (any Error).self) { try expr } The basic form for checking any error.
XCTAssertNoThrow(try expr) #expect(throws: Never.self) { try expr } The explicit way to assert that no error is thrown.

Action Items

  • Run grep -R "XCTAssert\|XCTUnwrap" . to find all legacy assertions.
  • Convert try XCTUnwrap() calls to try #require(). This is a direct and superior replacement.
  • Convert most XCTAssert...() calls to #expect(). Use #require() only for preconditions where continuing the test makes no sense.
  • Group related checks logically within a test. Since #expect continues on failure, you can naturally check multiple properties of an object in a single test.

3. Setup, Teardown, and State Lifecycle

Swift Testing replaces setUpWithError and tearDownWithError with a more natural, type-safe lifecycle using init() and deinit.

The Core Concept: A fresh, new instance of the test suite (struct or class) is created for each test function it contains. This is the cornerstone of test isolation, guaranteeing that state from one test cannot leak into another.

Method Replaces... Behavior
init() setUpWithError() The initializer for your suite. Put all setup code here. It can be async and throws.
deinit tearDownWithError() The deinitializer. Put cleanup code here. It runs automatically after each test. Note: deinit is only available on class or actor suite types, not structs. This is a common reason to choose a class for your suite.

Practical Example: Migrating a Database Test Suite

Before: The XCTest Way

final class DatabaseServiceXCTests: XCTestCase {
    var sut: DatabaseService!
    var tempDirectory: URL!

    override func setUpWithError() throws {
        try super.setUpWithError()
        tempDirectory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
        try FileManager.default.createDirectory(at: tempDirectory, withIntermediateDirectories: true)
        
        let testDatabase = TestDatabase(storageURL: tempDirectory)
        sut = DatabaseService(database: testDatabase)
    }

    override func tearDownWithError() throws {
        try FileManager.default.removeItem(at: tempDirectory)
        sut = nil
        tempDirectory = nil
        try super.tearDownWithError()
    }

    func testSavingUser() throws {
        let user = User(id: "user-1", name: "Alex")
        try sut.save(user)
        let loadedUser = try sut.loadUser(id: "user-1")
        XCTAssertNotNil(loadedUser)
    }
}

After: The Swift Testing Way (using class for deinit)

@Suite final class DatabaseServiceTests {
    // Using a class here to demonstrate `deinit` for cleanup.
    let sut: DatabaseService
    let tempDirectory: URL

    init() throws {
        // ARRANGE: Runs before EACH test in this suite.
        self.tempDirectory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
        try FileManager.default.createDirectory(at: tempDirectory, withIntermediateDirectories: true)
        
        let testDatabase = TestDatabase(storageURL: tempDirectory)
        self.sut = DatabaseService(database: testDatabase)
    }
    
    deinit {
        // TEARDOWN: Runs after EACH test.
        try? FileManager.default.removeItem(at: tempDirectory)
    }

    @Test func testSavingUser() throws {
        let user = User(id: "user-1", name: "Alex")
        try sut.save(user)
        #expect(try sut.loadUser(id: "user-1") != nil)
    }
}

Action Items

  • Convert test classes from XCTestCase to structs (preferred for automatic state isolation) or final classes.
  • Move setUpWithError logic into the suite's init().
  • Move tearDownWithError logic into the suite's deinit (and use a class or actor if needed).
  • Define the SUT and its dependencies as let properties, initialized in init().

4. Mastering Error Handling

Go beyond do/catch with a dedicated, expressive API for validating thrown errors.

Overload Replaces... Example & Use Case
#expect(throws: (any Error).self) Basic XCTAssertThrowsError Verifies that any error was thrown.
#expect(throws: BrewingError.self) Typed XCTAssertThrowsError Ensures an error of a specific type is thrown.
#expect(throws: BrewingError.outOfBeans) Specific Error XCTAssertThrowsError Validates a specific error value is thrown.
Inspecting the Thrown Error do/catch with switch Payload Introspection. The ultimate tool for errors with associated values. The macro returns the error, which you can then inspect.
swift let thrownError = #expect(throws: BrewingError.self) { try brew(beans: 0) } guard case let .notEnoughBeans(needed) = thrownError else { Issue.record("Wrong error case"); return } #expect(needed > 0)
#expect(throws: Never.self) XCTAssertNoThrow Explicitly asserts that a function does not throw. Ideal for happy-path tests.

5. Parameterized Tests: Drastically Reduce Boilerplate

Run a single test function with multiple argument sets to maximize coverage with minimal code. This is superior to a for-in loop because each argument set runs as an independent test, can be run in parallel, and failures are reported individually.

Pattern How to Use It & When
Single Collection @Test(arguments: [0, 100, -40])
The simplest form. Pass a collection of inputs.
Zipped Collections @Test(arguments: zip(inputs, expectedOutputs))
The most common and powerful pattern. Use zip to pair inputs and expected outputs, ensuring a one-to-one correspondence.
Multiple Collections @Test(arguments: ["USD", "EUR"], [1, 10, 100])
⚠️ Caution: Cartesian Product. This creates a test case for every possible combination of arguments. Use it deliberately when you need to test all combinations.

Example: Migrating Repetitive Tests to a Parameterized One

Before: The XCTest Way

func testFlavorVanillaContainsNoNuts() {
    let flavor = Flavor.vanilla
    XCTAssertFalse(flavor.containsNuts)
}
func testFlavorPistachioContainsNuts() {
    let flavor = Flavor.pistachio
    XCTAssertTrue(flavor.containsNuts)
}
func testFlavorChocolateContainsNoNuts() {
    let flavor = Flavor.chocolate
    XCTAssertFalse(flavor.containsNuts)
}

After: The Swift Testing Way using zip

@Test("Flavor nut content is correct", arguments: zip(
    [Flavor.vanilla, .pistachio, .chocolate],
    [false, true, false]
))
func testFlavorContainsNuts(flavor: Flavor, expected: Bool) {
    #expect(flavor.containsNuts == expected)
}

6. Conditional Execution & Skipping

Dynamically control which tests run based on feature flags, environment, or known issues.

Trait What It Does & How to Use It
.disabled("Reason") Unconditionally skips a test. The test is not run, but it is still compiled. Always provide a descriptive reason for CI visibility (e.g., "Flaky on CI, see FB12345").
.enabled(if: condition) Conditionally runs a test. The test only runs if the boolean condition is true. This is perfect for tests tied to feature flags or specific environments.
swift @Test(.enabled(if: FeatureFlags.isNewAPIEnabled)) func testNewAPI() { /* ... */ }
@available(...) OS Version-Specific Tests. Apply this attribute directly to the test function. It's better than a runtime #available check because it allows the test runner to know the test is skipped for platform reasons, which is cleaner in test reports.

7. Writing Assertions with Standard Swift

Swift Testing's philosophy is to use plain Swift expressions for assertions. For more complex checks like unordered collections or floating-point numbers, use the power of the Swift standard library.

Assertion Type How to Write It
Comparing Collections (Unordered) A simple == check on arrays fails if elements are the same but the order is different. To check for equality while ignoring order, convert both collections to a Set.

Brittle: #expect(tags == ["ios", "swift"]) // Fails if tags are ["swift", "ios"]
Robust: #expect(Set(tags) == Set(["swift", "ios"])) // Passes
Floating-Point Accuracy Floating-point math is imprecise. #expect(0.1 + 0.2 == 0.3) will fail. To ensure tests are robust, check that the absolute difference between the values is within an acceptable tolerance.

Fails: #expect(result == 0.3)
Passes: #expect(abs(result - 0.3) < 0.0001)

8. Structure and Organization at Scale

Use suites and tags to manage large and complex test bases.

Suites and Nested Suites

A @Suite groups related tests and can be nested for a clear hierarchy. Traits applied to a suite are inherited by all tests and nested suites within it.

Tags for Cross-Cutting Concerns

Tags associate tests with common characteristics (e.g., .network, .ui, .regression) regardless of their suite. This is invaluable for filtering.

  1. Define Tags in a Central File:
    // /Tests/Support/TestTags.swift
    import Testing
    
    extension Tag {
        @Tag static var fast: Self
        @Tag static var regression: Self
        @Tag static var flaky: Self
        @Tag static var networking: Self
    }
  2. Apply Tags & Filter:
    // Apply to a test or suite
    @Test("Username validation", .tags(.fast, .regression))
    func testUsername() { /* ... */ }
    
    // Run from CLI
    // swift test --filter .fast
    // swift test --skip .flaky
    // swift test --filter .networking --filter .regression
    
    // Filter in Xcode Test Plan
    // Add "fast" to the "Include Tags" field or "flaky" to the "Exclude Tags" field.

Power Move: Xcode UI Integration for Tags

Xcode 16 deeply integrates with tags, turning them into a powerful organizational tool.

  • Grouping by Tag in Test Navigator: In the Test Navigator (Cmd-6), click the tag icon at the top. This switches the view from the file hierarchy to one where tests are grouped by their tags. It's a fantastic way to visualize and run all tests related to a specific feature.
  • Test Report Insights: After a test run, the Test Report can automatically find patterns. Go to the Insights tab to see messages like "All 7 tests with the 'networking' tag failed." This immediately points you to systemic issues, saving significant debugging time.

9. Concurrency and Asynchronous Testing

Async/Await and Confirmations

  • Async Tests: Simply mark your test function async and use await.
  • Confirmations: To test APIs with completion handlers or that fire multiple times (like delegates or notifications), use the confirmation global function. It wraps the entire asynchronous operation and implicitly waits.
@Test("Delegate is notified 3 times")
func testDelegateNotifications() async {
    // The test operation is wrapped in an `await confirmation` call.
    // It will automatically wait or fail if the count isn't met in time.
    await confirmation("delegate.didUpdate was called", expectedCount: 3) { confirm in
        // `confirm` is a function passed to your closure. Call it when the event happens.
        let delegate = MockDelegate {
            confirm() // Call the confirmation
        }
        let sut = SystemUnderTest(delegate: delegate)

        // The action that triggers the events happens *inside* the closure.
        sut.performActionThatNotifiesThreeTimes()
    }
}

Advanced Asynchronous Patterns

Asserting an Event Never Happens

Use a confirmation with expectedCount: 0 to verify that a callback or delegate method is never called during an operation. If confirm() is called, the test will fail.

@Test("Logging out does not trigger a data sync")
func testLogoutDoesNotSync() async {
    await confirmation("data sync was triggered", expectedCount: 0) { confirm in
        let mockSyncEngine = MockSyncEngine {
            // If this is ever called, the test will automatically fail.
            confirm()
        }
        let sut = AccountManager(syncEngine: mockSyncEngine)
    
        sut.logout()
    }
}

Bridging Legacy Completion Handlers

For older asynchronous code that uses completion handlers, use withCheckedThrowingContinuation to wrap it in a modern async/await call that Swift Testing can work with.

func legacyFetch(completion: @escaping (Result<Data, Error>) -> Void) {
    // ... legacy async code ...
}

@Test func testLegacyFetch() async throws {
    let data = try await withCheckedThrowingContinuation { continuation in
        legacyFetch { result in
            continuation.resume(with: result)
        }
    }
    #expect(!data.isEmpty)
}

Controlling Parallelism

  • .serialized: Apply this trait to a @Test or @Suite to force its contents to run serially (one at a time). Use this as a temporary measure for legacy tests that are not thread-safe or have hidden state dependencies. The goal should be to refactor them to run in parallel.
  • .timeLimit: A safety net to prevent hung tests from stalling CI. The more restrictive (shorter) duration wins when applied at both the suite and test level.

10. Advanced API Cookbook

Feature What it Does & How to Use It
withKnownIssue Marks a test as an Expected Failure. It's better than .disabled for known bugs. The test still runs but won't fail the suite. Crucially, if the underlying bug gets fixed and the test passes, withKnownIssue will fail, alerting you to remove it.
CustomTestStringConvertible Provides custom, readable descriptions for your types in test failure logs. Conform your key models to this protocol to make debugging much easier.
.bug(id: "JIRA-123") Trait Associates a test directly with a ticket in your issue tracker. This adds invaluable context to test reports in Xcode and Xcode Cloud.
Test.current A static property (Test.current) that gives you runtime access to the current test's metadata, such as its name, tags, and source location. Useful for advanced custom logging.
Multiple #expect Calls Unlike XCTest where a failure might stop a test, #expect allows execution to continue. You can place multiple #expect calls in a single test to validate different properties of an object, and all failures will be reported together. There is no need for a special grouping macro.

11. Common Pitfalls and How to Avoid Them

A checklist of common mistakes developers make when adopting Swift Testing.

  1. Overusing #require()

    • The Pitfall: Using #require() for every check. This makes tests brittle and hides information. If the first #require() fails, the rest of the test is aborted, and you won't know if other things were also broken.
    • The Fix: Use #expect() for most checks. Only use #require() for essential setup conditions where the rest of the test would be nonsensical if they failed (e.g., a non-nil SUT, a valid URL).
  2. Forgetting State is Isolated

    • The Pitfall: Assuming that a property modified in one test will retain its value for the next test in the same suite.
    • The Fix: Remember that a new instance of the suite is created for every test. This is a feature, not a bug! All shared setup must happen in init(). Do not rely on state carrying over between tests.
  3. Accidentally Using a Cartesian Product

    • The Pitfall: Passing multiple collections to a parameterized test without zip, causing an exponential explosion of test cases (@Test(arguments: collectionA, collectionB)).
    • The Fix: Be deliberate. If you want one-to-one pairing, always use zip. Only use the multi-collection syntax when you explicitly want to test every possible combination.
  4. Ignoring the .serialized Trait for Unsafe Tests

    • The Pitfall: Migrating old, stateful tests that are not thread-safe and seeing them fail randomly due to parallel execution.
    • The Fix: As a temporary measure, apply the .serialized trait to the suite containing these tests. This forces them to run one-at-a-time, restoring the old behavior. The long-term goal should be to refactor the tests to be parallel-safe and remove the trait.

12. Migrating from XCTest

Swift Testing and XCTest can coexist in the same target, enabling an incremental migration.

Key Differences at a Glance

Feature XCTest Swift Testing
Test Discovery Method name must start with test... @Test attribute on any function or method.
Suite Type class MyTests: XCTestCase struct MyTests (preferred), class, or actor.
Assertions XCTAssert...() family of functions #expect() and #require() macros with Swift expressions.
Error Unwrapping try XCTUnwrap(...) try #require(...)
Setup/Teardown setUpWithError(), tearDownWithError() init(), deinit (on classes/actors)
Asynchronous Wait XCTestExpectation and wait(for:timeout:) await confirmation(...) { ... } block-based API.
Parallelism Opt-in, multi-process Opt-out, in-process via Swift Concurrency.

What NOT to Migrate (Yet)

Continue using XCTest for the following, as they are not currently supported by Swift Testing:

  • UI Automation Tests (using XCUIApplication)
  • Performance Tests (using XCTMetric and measure { ... })
  • Tests written in Objective-C

Appendix: Evergreen Testing Principles (The F.I.R.S.T. Principles)

These foundational principles are framework-agnostic, and Swift Testing is designed to make adhering to them easier than ever.

Principle Meaning Swift Testing Application
Fast Tests must execute in milliseconds. Lean on default parallelism. Use .serialized sparingly.
Isolated Tests must not depend on each other. Swift Testing enforces this by creating a new suite instance for every test. Random execution order helps surface violations.
Repeatable A test must produce the same result every time. Control all inputs (dates, network responses) with mocks/stubs. Reset state in init/deinit.
Self-Validating The test must automatically report pass or fail. Use #expect and #require. Never rely on print() for validation.
Timely Write tests alongside the production code. Use parameterized tests (@Test(arguments:)) to easily cover edge cases as you write code.

[# https://developer.apple.com/documentation/testing llms-full.txt

Swift Testing Overview

Skip Navigation

Framework

Swift Testing

Create and run tests for your Swift packages and Xcode projects.

Swift 6.0+Xcode 16.0+

The Swift logo on a blue gradient background that contains function, number, tag, and checkmark diamond symbols.

With Swift Testing you leverage powerful and expressive capabilities of the Swift programming language to develop tests with more confidence and less code. The library integrates seamlessly with Swift Package Manager testing workflow, supports flexible test organization, customizable metadata, and scalable test execution.

  • Define test functions almost anywhere with a single attribute.

  • Group related tests into hierarchies using Swift’s type system.

  • Integrate seamlessly with Swift concurrency.

  • Parameterize test functions across wide ranges of inputs.

  • Enable tests dynamically depending on runtime conditions.

  • Parallelize tests in-process.

  • Categorize tests using tags.

  • Associate bugs directly with the tests that verify their fixes or reproduce their problems.

\ \ Meet Swift Testing

\ \ Go further with Swift Testing

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

API Reference\ Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

API Reference\ Known issues

Highlight known issues when running tests.

API Reference\ Traits

Annotate test functions and suites, and customize their behavior.

Current page is Swift Testing

Adding Tags to Tests

Skip Navigation

Article

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

A complex package or project may contain hundreds or thousands of tests and suites. Some subset of those tests may share some common facet, such as being critical or flaky. The testing library includes a type of trait called tags that you can add to group and categorize tests.

Tags are different from test suites: test suites impose structure on test functions at the source level, while tags provide semantic information for a test that can be shared with any number of other tests across test suites, source files, and even test targets.

To add a tag to a test, use the tags(_:) trait. This trait takes a sequence of tags as its argument, and those tags are then applied to the corresponding test at runtime. If any tags are applied to a test suite, then all tests in that suite inherit those tags.

The testing library doesn’t assign any semantic meaning to any tags, nor does the presence or absence of tags affect how the testing library runs tests.

Tags themselves are instances of Tag and expressed as named constants declared as static members of Tag. To declare a named constant tag, use the Tag() macro:

extension Tag {
  @Tag static var legallyRequired: Self
}

@Test("Vendor's license is valid", .tags(.legallyRequired))
func licenseValid() { ... }

If two tags with the same name ( legallyRequired in the above example) are declared in different files, modules, or other contexts, the testing library treats them as equivalent.

If it’s important for a tag to be distinguished from similar tags declared elsewhere in a package or project (or its dependencies), use reverse-DNS naming to create a unique Swift symbol name for your tag:

extension Tag {
  enum com_example_foodtruck {}
}

extension Tag.com_example_foodtruck {
  @Tag static var extraSpecial: Tag
}

@Test(
  "Extra Special Sauce recipe is secret",
  .tags(.com_example_foodtruck.extraSpecial)
)
func secretSauce() { ... }

Tags must always be declared as members of Tag in an extension to that type or in a type nested within Tag. Redeclaring a tag under a second name has no effect and the additional name will not be recognized by the testing library. The following example is unsupported:

extension Tag {
  @Tag static var legallyRequired: Self // ✅ OK: Declaring a new tag.

  static var requiredByLaw: Self { // ❌ ERROR: This tag name isn't
                                   // recognized at runtime.
    legallyRequired
  }
}

If a tag is declared as a named constant outside of an extension to the Tag type (for example, at the root of a file or in another unrelated type declaration), it cannot be applied to test functions or test suites. The following declarations are unsupported:

@Tag let needsKetchup: Self // ❌ ERROR: Tags must be declared in an extension
                            // to Tag.
struct Food {
  @Tag var needsMustard: Self // ❌ ERROR: Tags must be declared in an extension
                              // to Tag.
}

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Adding tags to tests

Swift Test Overview

Skip Navigation

Structure

Test

A type representing a test or suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Test

An instance of this type may represent:

  • A type containing zero or more tests (i.e. a test suite);

  • An individual test function (possibly contained within a type); or

  • A test function parameterized over one or more sequences of inputs.

Two instances of this type are considered to be equal if the values of their id properties are equal.

struct Case

A single test case from a parameterized Test.

var associatedBugs: [Bug]

The set of bugs associated with this test.

var comments: [Comment]

The complete set of comments about this test from all of its traits.

var displayName: String?

The customized display name of this instance, if specified.

var isParameterized: Bool

Whether or not this test is parameterized.

var isSuite: Bool

Whether or not this instance is a test suite containing other tests.

var name: String

The name of this instance.

var sourceLocation: SourceLocation

The source location of this test.

var tags: Set<Tag>

The complete, unique set of tags associated with this test.

var timeLimit: Duration?

The maximum amount of time this test’s cases may run for.

var traits: [any Trait]

The set of traits added to this instance when it was initialized.

static var current: Test?

The test that is running on the current task, if any.

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ Identifiable Implementations

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Test

Adding Comments to Tests

Skip Navigation

Article

Adding comments to tests

Add comments to provide useful information about tests.

It’s often useful to add comments to code to:

  • Provide context or background information about the code’s purpose

  • Explain how complex code implemented

  • Include details which may be helpful when diagnosing issues

Test code is no different and can benefit from explanatory code comments, but often test issues are shown in places where the source code of the test is unavailable such as in continuous integration (CI) interfaces or in log files.

Seeing comments related to tests in these contexts can help diagnose issues more quickly. Comments can be added to test declarations and the testing library will automatically capture and show them when issues are recorded.

To include a comment on a test or suite, write an ordinary Swift code comment immediately before its @Test or @Suite attribute:

// Assumes the standard lunch menu includes a taco
@Test func lunchMenu() {
  let foodTruck = FoodTruck(
    menu: .lunch,
    ingredients: [.tortillas, .cheese]
  )
  #expect(foodTruck.menu.contains { $0 is Taco })
}

The comment, // Assumes the standard lunch menu includes a taco, is added to the test.

The following language comment styles are supported:

Syntax Style
// ... Line comment
/// ... Documentation line comment
/* ... */ Block comment
/** ... */ Documentation block comment

Test comments which are automatically added from source code comments preserve their original formatting, including any prefixes like // or /**. This is because the whitespace and formatting of comments can be meaningful in some circumstances or aid in understanding the comment — for example, when a comment includes an example code snippet or diagram.

As in normal code, comments on tests are generally most useful when they:

  • Add information that isn’t obvious from reading the code

  • Provide useful information about the operation or motivation of a test

If a test is related to a bug or issue, consider using the Bug trait instead of comments. For more information, see Associating bugs with tests.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Adding comments to tests

Organizing Test Functions

Skip Navigation

Article

Organizing test functions with suite types

Organize tests into test suites.

When working with a large selection of test functions, it can be helpful to organize them into test suites.

A test function can be added to a test suite in one of two ways:

  • By placing it in a Swift type.

  • By placing it in a Swift type and annotating that type with the @Suite attribute.

The @Suite attribute isn’t required for the testing library to recognize that a type contains test functions, but adding it allows customization of a test suite’s appearance in the IDE and at the command line. If a trait such as tags(_:) or disabled(_:sourceLocation:) is applied to a test suite, it’s automatically inherited by the tests contained in the suite.

In addition to containing test functions and any other members that a Swift type might contain, test suite types can also contain additional test suites nested within them. To add a nested test suite type, simply declare an additional type within the scope of the outer test suite type.

By default, tests contained within a suite run in parallel with each other. For more information about test parallelization, see Running tests serially or in parallel.

To customize a test suite’s name, supply a string literal as an argument to the @Suite attribute:

@Suite("Food truck tests") struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}

To further customize the appearance and behavior of a test function, use traits such as tags(_:).

If a type contains a test function declared as an instance method (that is, without either the static or class keyword), the testing library calls that test function at runtime by initializing an instance of the type, then calling the test function on that instance. If a test suite type contains multiple test functions declared as instance methods, each one is called on a distinct instance of the type. Therefore, the following test suite and test function:

@Suite struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}

Are equivalent to:

@Suite struct FoodTruckTests {
  func foodTruckExists() { ... }

  @Test static func staticFoodTruckExists() {
    let instance = FoodTruckTests()
    instance.foodTruckExists()
  }
}

When using a type as a test suite, it’s subject to some constraints that are not otherwise applied to Swift types.

If a type contains test functions declared as instance methods, it must be possible to initialize an instance of the type with a zero-argument initializer. The initializer may be any combination of:

  • implicit or explicit

  • synchronous or asynchronous

  • throwing or non-throwing

  • private, fileprivate, internal, package, or public

For example:

@Suite struct FoodTruckTests {
  var batteryLevel = 100

  @Test func foodTruckExists() { ... } // ✅ OK: The type has an implicit init().
}

@Suite struct CashRegisterTests {
  private init(cashOnHand: Decimal = 0.0) async throws { ... }

  @Test func calculateSalesTax() { ... } // ✅ OK: The type has a callable init().
}

struct MenuTests {
  var foods: [Food]
  var prices: [Food: Decimal]

  @Test static func specialOfTheDay() { ... } // ✅ OK: The function is static.
  @Test func orderAllFoods() { ... } // ❌ ERROR: The suite type requires init().
}

The compiler emits an error when presented with a test suite that doesn’t meet this requirement.

Although @available can be applied to a test function to limit its availability at runtime, a test suite type (and any types that contain it) must not be annotated with the @available attribute:

@Suite struct FoodTruckTests { ... } // ✅ OK: The type is always available.

@available(macOS 11.0, *) // ❌ ERROR: The suite type must always be available.
@Suite struct CashRegisterTests { ... }

@available(macOS 11.0, *) struct MenuItemTests { // ❌ ERROR: The suite type's
                                                 // containing type must always
                                                 // be available too.
  @Suite struct BurgerTests { ... }
}

The compiler emits an error when presented with a test suite that doesn’t meet this requirement.

Defining test functions

Define a test function to validate that code is working correctly.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Organizing test functions with suite types

Custom Test Argument Encoding

Skip Navigation

Protocol

CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol CustomTestArgumentEncodable : Sendable

Implementing parameterized tests

The testing library checks whether a test argument conforms to this protocol, or any of several other known protocols, when running selected test cases. When a test argument conforms to this protocol, that conformance takes highest priority, and the testing library will then call encodeTestArgument(to:) on the argument. A type that conforms to this protocol is not required to conform to either Encodable or Decodable.

See Implementing parameterized tests for a list of the other supported ways to allow running selected test cases.

func encodeTestArgument(to: some Encoder) throws

Encode this test argument.

Required

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

struct Case

A single test case from a parameterized Test.

Current page is CustomTestArgumentEncodable

Defining Test Functions

Skip Navigation

Article

Defining test functions

Define a test function to validate that code is working correctly.

Defining a test function for a Swift package or project is straightforward.

To import the testing library, add the following to the Swift source file that contains the test:

import Testing

To declare a test function, write a Swift function declaration that doesn’t take any arguments, then prefix its name with the @Test attribute:

@Test func foodTruckExists() {
  // Test logic goes here.
}

This test function can be present at file scope or within a type. A type containing test functions is automatically a test suite and can be optionally annotated with the @Suite attribute. For more information about suites, see Organizing test functions with suite types.

Note that, while this function is a valid test function, it doesn’t actually perform any action or test any code. To check for expected values and outcomes in test functions, add expectations to the test function.

To customize a test function’s name as presented in an IDE or at the command line, supply a string literal as an argument to the @Test attribute:

@Test("Food truck exists") func foodTruckExists() { ... }

To further customize the appearance and behavior of a test function, use traits such as tags(_:).

As with other Swift functions, test functions can be marked async and throws to annotate them as concurrent or throwing, respectively. If a test is only safe to run in the main actor’s execution context (that is, from the main thread of the process), it can be annotated @MainActor:

@Test @MainActor func foodTruckExists() async throws { ... }

If a test function can only run on newer versions of an operating system or of the Swift language, use the @available attribute when declaring it. Use the message argument of the @available attribute to specify a message to log if a test is unable to run due to limited availability:

@available(macOS 11.0, *)
@available(swift, introduced: 8.0, message: "Requires Swift 8.0 features to run")
@Test func foodTruckExists() { ... }

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Defining test functions

Interpreting Bug Identifiers

Skip Navigation

Article

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

The testing library supports two distinct ways to identify a bug:

  1. A URL linking to more information about the bug; and

  2. A unique identifier in the bug’s associated bug-tracking system.

A bug may have both an associated URL and an associated unique identifier. It must have at least one or the other in order for the testing library to be able to interpret it correctly.

To create an instance of Bug with a URL, use the bug(_:_:) trait. At compile time, the testing library will validate that the given string can be parsed as a URL according to RFC 3986.

To create an instance of Bug with a bug’s unique identifier, use the bug(_:id:_:) trait. The testing library does not require that a bug’s unique identifier match any particular format, but will interpret unique identifiers starting with "FB" as referring to bugs tracked with the Apple Feedback Assistant. For convenience, you can also directly pass an integer as a bug’s identifier using bug(_:id:_:).

Trait Function Inferred Bug-Tracking System
.bug(id: 12345) None
.bug(id: "12345") None
.bug("https://www.example.com?id=12345", id: "12345") None
.bug("https://github.com/swiftlang/swift/pull/12345") GitHub Issues for the Swift project
.bug("https://bugs.webkit.org/show_bug.cgi?id=12345") WebKit Bugzilla
.bug(id: "FB12345") Apple Feedback Assistant

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Interpreting bug identifiers

Limiting Test Execution Time

Skip Navigation

Article

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

Some tests may naturally run slowly: they may require significant system resources to complete, may rely on downloaded data from a server, or may otherwise be dependent on external factors.

If a test may hang indefinitely or may consume too many system resources to complete effectively, consider setting a time limit for it so that it’s marked as failing if it runs for an excessive amount of time. Use the timeLimit(_:) trait as an upper bound:

@Test(.timeLimit(.minutes(60))
func serve100CustomersInOneHour() async {
  for _ in 0 ..< 100 {
    let customer = await Customer.next()
    await customer.order()
    ...
  }
}

If the above test function takes longer than an hour (60 x 60 seconds) to execute, the task in which it’s running is cancelled and the test fails with an issue of kind Issue.Kind.timeLimitExceeded(timeLimitComponents:).

The testing library may adjust the specified time limit for performance reasons or to ensure tests have enough time to run. In particular, a granularity of (by default) one minute is applied to tests. The testing library can also be configured with a maximum time limit per test that overrides any applied time limit traits.

When a time limit is applied to a test suite, it’s recursively applied to all test functions and child test suites within that suite.

When a time limit is applied to a parameterized test function, it’s applied to each invocation separately so that if only some arguments cause failures, then successful arguments aren’t incorrectly marked as failing too.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is Limiting the running time of tests

Test Scoping Protocol

Skip Navigation

Protocol

TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Swift 6.1+Xcode 16.3+

protocol TestScoping : Sendable

Provide custom scope for tests by implementing the scopeProvider(for:testCase:) method, returning a type that conforms to this protocol. Create a custom scope to consolidate common set-up and tear-down logic for tests which have similar needs, which allows each test function to focus on the unique aspects of its test.

func provideScope(for: Test, testCase: Test.Case?, performing: () async throws -> Void) async throws

Provide custom execution scope for a function call which is related to the specified test or test case.

Required

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

Current page is TestScoping

Event Confirmation Type

Skip Navigation

Structure

Confirmation

A type that can be used to confirm that an event occurs zero or more times.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Confirmation

Testing asynchronous code

Migrating a test from XCTest

func callAsFunction(count: Int)

Confirm this confirmation.

func confirm(count: Int)

Confirm this confirmation.

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

Current page is Confirmation

Tag Type Overview

Skip Navigation

Structure

Tag

A type representing a tag that can be applied to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Tag

Adding tags to tests

To apply tags to a test, use the tags(_:) function.

struct List

A type representing one or more tags applied to a test.

API Reference\ CodingKeyRepresentable Implementations

API Reference\ Comparable Implementations

API Reference\ CustomStringConvertible Implementations

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Tag

SuiteTrait Protocol

Skip Navigation

Protocol

SuiteTrait

A protocol describing a trait that you can add to a test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol SuiteTrait : Trait

The testing library defines a number of traits that you can add to test suites. You can also define your own traits by creating types that conform to this protocol, or to the TestTrait protocol.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

Required Default implementation provided.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is SuiteTrait

Trait Protocol

Skip Navigation

Protocol

Trait

A protocol describing traits that can be added to a test function or to a test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol Trait : Sendable

The testing library defines a number of traits that can be added to test functions and to test suites. Define your own traits by creating types that conform to TestTrait or SuiteTrait:

TestTrait

Conform to this type in traits that you add to test functions.

SuiteTrait

Conform to this type in traits that you add to test suites.

You can add a trait that conforms to both TestTrait and SuiteTrait to test functions and test suites.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

static func tags(Tag...) -> Self

Construct a list of tags to apply to a test.

var comments: [Comment]

The user-provided comments for this trait.

Required Default implementation provided.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self.TestScopeProvider?

Get this trait’s scope provider for the specified test and optional test case.

Required Default implementations provided.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

Required Default implementation provided.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is Trait

Expectation Failed Error

Skip Navigation

Structure

ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ExpectationFailedError

The testing library throws instances of this type when the #require() macro records an issue.

var expectation: Expectation

The expectation that failed.

struct Expectation

A type describing an expectation that has been evaluated.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

Current page is ExpectationFailedError

Time Limit Trait

Skip Navigation

Structure

TimeLimitTrait

A type that defines a time limit to apply to a test.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

struct TimeLimitTrait

To add this trait to a test, use timeLimit(_:).

struct Duration

A type representing the duration of a time limit applied to a test.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var timeLimit: Duration

The maximum amount of time a test may run for before timing out.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

Current page is TimeLimitTrait

Swift Expectation Type

Skip Navigation

Structure

Expectation

A type describing an expectation that has been evaluated.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Expectation

var isPassing: Bool

Whether the expectation passed or failed.

var isRequired: Bool

Whether or not the expectation was required to pass.

var sourceLocation: SourceLocation

The source location where this expectation was evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

Current page is Expectation

Parameterized Testing in Swift

Skip Navigation

Article

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

Some tests need to be run over many different inputs. For instance, a test might need to validate all cases of an enumeration. The testing library lets developers specify one or more collections to iterate over during testing, with the elements of those collections being forwarded to a test function. An invocation of a test function with a particular set of argument values is called a test case.

By default, the test cases of a test function run in parallel with each other. For more information about test parallelization, see Running tests serially or in parallel.

It is very common to want to run a test n times over an array containing the values that should be tested. Consider the following test function:

enum Food {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available")
func foodsAvailable() async throws {
  for food: Food in [.burger, .iceCream, .burrito, .noodleBowl, .kebab] {
    let foodTruck = FoodTruck(selling: food)
    #expect(await foodTruck.cook(food))
  }
}

If this test function fails for one of the values in the array, it may be unclear which value failed. Instead, the test function can be parameterized over the various inputs:

enum Food {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available", arguments: [Food.burger, .iceCream, .burrito, .noodleBowl, .kebab])
func foodAvailable(_ food: Food) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food))
}

When passing a collection to the @Test attribute for parameterization, the testing library passes each element in the collection, one at a time, to the test function as its first (and only) argument. Then, if the test fails for one or more inputs, the corresponding diagnostics can clearly indicate which inputs to examine.

The previous example includes a hard-coded list of Food cases to test. If Food is an enumeration that conforms to CaseIterable, you can instead write:

enum Food: CaseIterable {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available", arguments: Food.allCases)
func foodAvailable(_ food: Food) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food))
}

This way, if a new case is added to the Food enumeration, it’s automatically tested by this function.

It is possible to parameterize a test function over a closed range of integers:

@Test("Can make large orders", arguments: 1 ... 100)
func makeLargeOrder(count: Int) async throws {
  let foodTruck = FoodTruck(selling: .burger)
  #expect(await foodTruck.cook(.burger, quantity: count))
}

It’s possible to test more than one collection. Consider the following test function:

@Test("Can make large orders", arguments: Food.allCases, 1 ... 100)
func makeLargeOrder(of food: Food, count: Int) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food, quantity: count))
}

Elements from the first collection are passed as the first argument to the test function, elements from the second collection are passed as the second argument, and so forth.

Assuming there are five cases in the Food enumeration, this test function will, when run, be invoked 500 times (5 x 100) with every possible combination of food and order size. These combinations are referred to as the collections’ Cartesian product.

To avoid the combinatoric semantics shown above, use zip():

@Test("Can make large orders", arguments: zip(Food.allCases, 1 ... 100))
func makeLargeOrder(of food: Food, count: Int) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food, quantity: count))
}

The zipped sequence will be “destructured” into two arguments automatically, then passed to the test function for evaluation.

This revised test function is invoked once for each tuple in the zipped sequence, for a total of five invocations instead of 500 invocations. In other words, this test function is passed the inputs (.burger, 1), (.iceCream, 2), …, (.kebab, 5) instead of (.burger, 1), (.burger, 2), (.burger, 3), …, (.kebab, 99), (.kebab, 100).

If a parameterized test meets certain requirements, the testing library allows people to run specific test cases it contains. This can be useful when a test has many cases but only some are failing since it enables re-running and debugging the failing cases in isolation.

To support running selected test cases, it must be possible to deterministically match the test case’s arguments. When someone attempts to run selected test cases of a parameterized test function, the testing library evaluates each argument of the tests’ cases for conformance to one of several known protocols, and if all arguments of a test case conform to one of those protocols, that test case can be run selectively. The following lists the known protocols, in precedence order (highest to lowest):

  1. CustomTestArgumentEncodable

  2. RawRepresentable, where RawValue conforms to Encodable

  3. Encodable

  4. Identifiable, where ID conforms to Encodable

If any argument of a test case doesn’t meet one of the above requirements, then the overall test case cannot be run selectively.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Implementing parameterized tests

Condition Trait

Skip Navigation

Structure

ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ConditionTrait

Migrating a test from XCTest

To add this trait to a test, use one of the following functions:

var comments: [Comment]

The user-provided comments for this trait.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var sourceLocation: SourceLocation

The source location where this trait is specified.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ConditionTrait

SourceLocation in Swift

Skip Navigation

Structure

SourceLocation

A type representing a location in source code.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct SourceLocation

init(fileID: String, filePath: String, line: Int, column: Int)

Initialize an instance of this type with the specified location details.

var column: Int

The column in the source file.

var fileID: String

The file ID of the source file.

var fileName: String

The name of the source file.

var line: Int

The line in the source file.

var moduleName: String

The name of the module containing the source file.

API Reference\ Comparable Implementations

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

Current page is SourceLocation

Bug Reporting Structure

Skip Navigation

Structure

Bug

A type that represents a bug report tracked by a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Bug

Interpreting bug identifiers

Adding comments to tests

To add this trait to a test, use one of the following functions:

var id: String?

A unique identifier in this bug’s associated bug-tracking system, if available.

var title: Comment?

The human-readable title of the bug, if specified by the test author.

var url: String?

A URL that links to more information about the bug, if available.

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Bug

Swift Test Traits

Skip Navigation

Collection

API Collection

Traits

Annotate test functions and suites, and customize their behavior.

Pass built-in traits to test functions or suite types to comment, categorize, classify, and modify the runtime behavior of test suites and test functions. Implement the TestTrait, and SuiteTrait protocols to create your own types that customize the behavior of your tests.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Running tests serially or in parallel

Control whether tests run serially or in parallel.

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Traits

Custom Test String

Skip Navigation

Protocol

CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol CustomTestStringConvertible

Values whose types conform to this protocol use it to describe themselves when they are present as part of the output of a test. For example, this protocol affects the display of values that are passed as arguments to test functions or that are elements of an expectation failure.

By default, the testing library converts values to strings using String(describing:). The resulting string may be inappropriate for some types and their values. If the type of the value is made to conform to CustomTestStringConvertible, then the value of its testDescription property will be used instead.

For example, consider the following type:

enum Food: CaseIterable {
  case paella, oden, ragu
}

If an array of cases from this enumeration is passed to a parameterized test function:

@Test(arguments: Food.allCases)
func isDelicious(_ food: Food) { ... }

Then the values in the array need to be presented in the test output, but the default description of a value may not be adequately descriptive:

◇ Passing argument food → .paella to isDelicious(_:)
◇ Passing argument food → .oden to isDelicious(_:)
◇ Passing argument food → .ragu to isDelicious(_:)

By adopting CustomTestStringConvertible, customized descriptions can be included:

extension Food: CustomTestStringConvertible {
  var testDescription: String {
    switch self {
    case .paella:
      "paella valenciana"
    case .oden:
      "おでん"
    case .ragu:
      "ragù alla bolognese"
    }
  }
}

The presentation of these values will then reflect the value of the testDescription property:

◇ Passing argument food → paella valenciana to isDelicious(_:)
◇ Passing argument food → おでん to isDelicious(_:)
◇ Passing argument food → ragù alla bolognese to isDelicious(_:)

var testDescription: String

A description of this instance to use when presenting it in a test’s output.

Required Default implementation provided.

struct Expectation

A type describing an expectation that has been evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

Current page is CustomTestStringConvertible

Swift Testing Issues

Skip Navigation

Structure

Issue

A type describing a failure or warning which occurred during a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Issue

Associating bugs with tests

Interpreting bug identifiers

var comments: [Comment]

Any comments provided by the developer and associated with this issue.

var error: (any Error)?

The error which was associated with this issue, if any.

var kind: Issue.Kind

The kind of issue this value represents.

var sourceLocation: SourceLocation?

The location in source where this issue occurred, if available.

static func record(any Error, Comment?, sourceLocation: SourceLocation) -> Issue

Record a new issue when a running test unexpectedly catches an error.

static func record(Comment?, sourceLocation: SourceLocation) -> Issue

Record an issue when a running test fails unexpectedly.

enum Kind

Kinds of issues which may be recorded.

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

Current page is Issue

Migrating from XCTest

Skip Navigation

Article

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

The testing library provides much of the same functionality of XCTest, but uses its own syntax to declare test functions and types. Here, you’ll learn how to convert XCTest-based content to use the testing library instead.

XCTest and the testing library are available from different modules. Instead of importing the XCTest module, import the Testing module:

// Before
import XCTest

// After
import Testing

A single source file can contain tests written with XCTest as well as other tests written with the testing library. Import both XCTest and Testing if a source file contains mixed test content.

XCTest groups related sets of test methods in test classes: classes that inherit from the XCTestCase class provided by the XCTest framework. The testing library doesn’t require that test functions be instance members of types. Instead, they can be free or global functions, or can be static or class members of a type.

If you want to group your test functions together, you can do so by placing them in a Swift type. The testing library refers to such a type as a suite. These types do not need to be classes, and they don’t inherit from XCTestCase.

To convert a subclass of XCTestCase to a suite, remove the XCTestCase conformance. It’s also generally recommended that a Swift structure or actor be used instead of a class because it allows the Swift compiler to better-enforce concurrency safety:

// Before
class FoodTruckTests: XCTestCase {
  ...
}

// After
struct FoodTruckTests {
  ...
}

For more information about suites and how to declare and customize them, see Organizing test functions with suite types.

In XCTest, code can be scheduled to run before and after a test using the setUp() and tearDown() family of functions. When writing tests using the testing library, implement init() and/or deinit instead:

// Before
class FoodTruckTests: XCTestCase {
  var batteryLevel: NSNumber!
  override func setUp() async throws {
    batteryLevel = 100
  }
  ...
}

// After
struct FoodTruckTests {
  var batteryLevel: NSNumber
  init() async throws {
    batteryLevel = 100
  }
  ...
}

The use of async and throws is optional. If teardown is needed, declare your test suite as a class or as an actor rather than as a structure and implement deinit:

// Before
class FoodTruckTests: XCTestCase {
  var batteryLevel: NSNumber!
  override func setUp() async throws {
    batteryLevel = 100
  }
  override func tearDown() {
    batteryLevel = 0 // drain the battery
  }
  ...
}

// After
final class FoodTruckTests {
  var batteryLevel: NSNumber
  init() async throws {
    batteryLevel = 100
  }
  deinit {
    batteryLevel = 0 // drain the battery
  }
  ...
}

The testing library represents individual tests as functions, similar to how they are represented in XCTest. However, the syntax for declaring a test function is different. In XCTest, a test method must be a member of a test class and its name must start with test. The testing library doesn’t require a test function to have any particular name. Instead, it identifies a test function by the presence of the @Test attribute:

// Before
class FoodTruckTests: XCTestCase {
  func testEngineWorks() { ... }
  ...
}

// After
struct FoodTruckTests {
  @Test func engineWorks() { ... }
  ...
}

As with XCTest, the testing library allows test functions to be marked async, throws, or async- throws, and to be isolated to a global actor (for example, by using the @MainActor attribute.)

For more information about test functions and how to declare and customize them, see Defining test functions.

XCTest uses a family of approximately 40 functions to assert test requirements. These functions are collectively referred to as XCTAssert(). The testing library has two replacements, expect(_:_:sourceLocation:) and require(_:_:sourceLocation:). They both behave similarly to XCTAssert() except that require(_:_:sourceLocation:) throws an error if its condition isn’t met:

// Before
func testEngineWorks() throws {
  let engine = FoodTruck.shared.engine
  XCTAssertNotNil(engine.parts.first)
  XCTAssertGreaterThan(engine.batteryLevel, 0)
  try engine.start()
  XCTAssertTrue(engine.isRunning)
}

// After
@Test func engineWorks() throws {
  let engine = FoodTruck.shared.engine
  try #require(engine.parts.first != nil)
  #expect(engine.batteryLevel > 0)
  try engine.start()
  #expect(engine.isRunning)
}

XCTest also has a function, XCTUnwrap(), that tests if an optional value is nil and throws an error if it is. When using the testing library, you can use require(_:_:sourceLocation:) with optional expressions to unwrap them:

// Before
func testEngineWorks() throws {
  let engine = FoodTruck.shared.engine
  let part = try XCTUnwrap(engine.parts.first)
  ...
}

// After
@Test func engineWorks() throws {
  let engine = FoodTruck.shared.engine
  let part = try #require(engine.parts.first)
  ...
}

XCTest has a function, XCTFail(), that causes a test to fail immediately and unconditionally. This function is useful when the syntax of the language prevents the use of an XCTAssert() function. To record an unconditional issue using the testing library, use the record(_:sourceLocation:) function:

// Before
func testEngineWorks() {
  let engine = FoodTruck.shared.engine
  guard case .electric = engine else {
    XCTFail("Engine is not electric")
    return
  }
  ...
}

// After
@Test func engineWorks() {
  let engine = FoodTruck.shared.engine
  guard case .electric = engine else {
    Issue.record("Engine is not electric")
    return
  }
  ...
}

The following table includes a list of the various XCTAssert() functions and their equivalents in the testing library:

XCTest Swift Testing
XCTAssert(x), XCTAssertTrue(x) #expect(x)
XCTAssertFalse(x) #expect(!x)
XCTAssertNil(x) #expect(x == nil)
XCTAssertNotNil(x) #expect(x != nil)
XCTAssertEqual(x, y) #expect(x == y)
XCTAssertNotEqual(x, y) #expect(x != y)
XCTAssertIdentical(x, y) #expect(x === y)
XCTAssertNotIdentical(x, y) #expect(x !== y)
XCTAssertGreaterThan(x, y) #expect(x > y)
XCTAssertGreaterThanOrEqual(x, y) #expect(x >= y)
XCTAssertLessThanOrEqual(x, y) #expect(x <= y)
XCTAssertLessThan(x, y) #expect(x < y)
XCTAssertThrowsError(try f()) #expect(throws: (any Error).self) { try f() }
XCTAssertThrowsError(try f()) { error in … } let error = #expect(throws: (any Error).self) { try f() }
XCTAssertNoThrow(try f()) #expect(throws: Never.self) { try f() }
try XCTUnwrap(x) try #require(x)
XCTFail("…") Issue.record("…")

The testing library doesn’t provide an equivalent of XCTAssertEqual(_:_:accuracy:_:file:line:). To compare two numeric values within a specified accuracy, use isApproximatelyEqual() from swift-numerics.

An instance of an XCTestCase subclass can set its continueAfterFailure property to false to cause a test to stop running after a failure occurs. XCTest stops an affected test by throwing an Objective-C exception at the time the failure occurs.

The behavior of an exception thrown through a Swift stack frame is undefined. If an exception is thrown through an async Swift function, it typically causes the process to terminate abnormally, preventing other tests from running.

The testing library doesn’t use exceptions to stop test functions. Instead, use the require(_:_:sourceLocation:) macro, which throws a Swift error on failure:

// Before
func testTruck() async {
  continueAfterFailure = false
  XCTAssertTrue(FoodTruck.shared.isLicensed)
  ...
}

// After
@Test func truck() throws {
  try #require(FoodTruck.shared.isLicensed)
  ...
}

When using either continueAfterFailure or require(_:_:sourceLocation:), other tests will continue to run after the failed test method or test function.

XCTest has a class, XCTestExpectation, that represents some asynchronous condition. You create an instance of this class (or a subclass like XCTKeyPathExpectation) using an initializer or a convenience method on XCTestCase. When the condition represented by an expectation occurs, the developer fulfills the expectation. Concurrently, the developer waits for the expectation to be fulfilled using an instance of XCTWaiter or using a convenience method on XCTestCase.

Wherever possible, prefer to use Swift concurrency to validate asynchronous conditions. For example, if it’s necessary to determine the result of an asynchronous Swift function, it can be awaited with await. For a function that takes a completion handler but which doesn’t use await, a Swift continuation can be used to convert the call into an async-compatible one.

Some tests, especially those that test asynchronously-delivered events, cannot be readily converted to use Swift concurrency. The testing library offers functionality called confirmations which can be used to implement these tests. Instances of Confirmation are created and used within the scope of the functions confirmation(_:expectedCount:isolation:sourceLocation:_:) and confirmation(_:expectedCount:isolation:sourceLocation:_:).

Confirmations function similarly to the expectations API of XCTest, however, they don’t block or suspend the caller while waiting for a condition to be fulfilled. Instead, the requirement is expected to be confirmed (the equivalent of fulfilling an expectation) before confirmation() returns, and records an issue otherwise:

// Before
func testTruckEvents() async {
  let soldFood = expectation(description: "…")
  FoodTruck.shared.eventHandler = { event in
    if case .soldFood = event {
      soldFood.fulfill()
    }
  }
  await Customer().buy(.soup)
  await fulfillment(of: [soldFood])
  ...
}

// After
@Test func truckEvents() async {
  await confirmation("…") { soldFood in
    FoodTruck.shared.eventHandler = { event in
      if case .soldFood = event {
        soldFood()
      }
    }
    await Customer().buy(.soup)
  }
  ...
}

By default, XCTestExpectation expects to be fulfilled exactly once, and will record an issue in the current test if it is not fulfilled or if it is fulfilled more than once. Confirmation behaves the same way and expects to be confirmed exactly once by default. You can configure the number of times an expectation should be fulfilled by setting its expectedFulfillmentCount property, and you can pass a value for the expectedCount argument of confirmation(_:expectedCount:isolation:sourceLocation:_:) for the same purpose.

XCTestExpectation has a property, assertForOverFulfill, which when set to false allows an expectation to be fulfilled more times than expected without causing a test failure. When using a confirmation, you can pass a range to confirmation(_:expectedCount:isolation:sourceLocation:_:) as its expected count to indicate that it must be confirmed at least some number of times:

// Before
func testRegularCustomerOrders() async {
  let soldFood = expectation(description: "…")
  soldFood.expectedFulfillmentCount = 10
  soldFood.assertForOverFulfill = false
  FoodTruck.shared.eventHandler = { event in
    if case .soldFood = event {
      soldFood.fulfill()
    }
  }
  for customer in regularCustomers() {
    await customer.buy(customer.regularOrder)
  }
  await fulfillment(of: [soldFood])
  ...
}

// After
@Test func regularCustomerOrders() async {
  await confirmation(
    "…",
    expectedCount: 10...
  ) { soldFood in
    FoodTruck.shared.eventHandler = { event in
      if case .soldFood = event {
        soldFood()
      }
    }
    for customer in regularCustomers() {
      await customer.buy(customer.regularOrder)
    }
  }
  ...
}

Any range expression with a lower bound (that is, whose type conforms to both RangeExpression<Int> and Sequence<Int>) can be used with confirmation(_:expectedCount:isolation:sourceLocation:_:). You must specify a lower bound for the number of confirmations because, without one, the testing library cannot tell if an issue should be recorded when there have been zero confirmations.

When using XCTest, the XCTSkip error type can be thrown to bypass the remainder of a test function. As well, the XCTSkipIf() and XCTSkipUnless() functions can be used to conditionalize the same action. The testing library allows developers to skip a test function or an entire test suite before it starts running using the ConditionTrait trait type. Annotate a test suite or test function with an instance of this trait type to control whether it runs:

// Before
class FoodTruckTests: XCTestCase {
  func testArepasAreTasty() throws {
    try XCTSkipIf(CashRegister.isEmpty)
    try XCTSkipUnless(FoodTruck.sells(.arepas))
    ...
  }
  ...
}

// After
@Suite(.disabled(if: CashRegister.isEmpty))
struct FoodTruckTests {
  @Test(.enabled(if: FoodTruck.sells(.arepas)))
  func arepasAreTasty() {
    ...
  }
  ...
}

A test may have a known issue that sometimes or always prevents it from passing. When written using XCTest, such tests can call XCTExpectFailure(_:options:failingBlock:) to tell XCTest and its infrastructure that the issue shouldn’t cause the test to fail. The testing library has an equivalent function with synchronous and asynchronous variants:

This function can be used to annotate a section of a test as having a known issue:

// Before
func testGrillWorks() async {
  XCTExpectFailure("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  }
  ...
}

If a test may fail intermittently, the call to XCTExpectFailure(_:options:failingBlock:) can be marked non-strict. When using the testing library, specify that the known issue is intermittent instead:

// Before
func testGrillWorks() async {
  XCTExpectFailure(
    "Grill may need fuel",
    options: .nonStrict()
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue(
    "Grill may need fuel",
    isIntermittent: true
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

Additional options can be specified when calling XCTExpectFailure():

  • isEnabled can be set to false to skip known-issue matching (for instance, if a particular issue only occurs under certain conditions)

  • issueMatcher can be set to a closure to allow marking only certain issues as known and to allow other issues to be recorded as test failures

The testing library includes overloads of withKnownIssue() that take additional arguments with similar behavior:

To conditionally enable known-issue matching or to match only certain kinds of issues:

// Before
func testGrillWorks() async {
  let options = XCTExpectedFailure.Options()
  options.isEnabled = FoodTruck.shared.hasGrill
  options.issueMatcher = { issue in
    issue.type == thrownError
  }
  XCTExpectFailure(
    "Grill is out of fuel",
    options: options
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  } when: {
    FoodTruck.shared.hasGrill
  } matching: { issue in
    issue.error != nil
  }
  ...
}

By default, the testing library runs all tests in a suite in parallel. The default behavior of XCTest is to run each test in a suite sequentially. If your tests use shared state such as global variables, you may see unexpected behavior including unreliable test outcomes when you run tests in parallel.

Annotate your test suite with serialized to run tests within that suite serially:

// Before
class RefrigeratorTests : XCTestCase {
  func testLightComesOn() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    XCTAssertEqual(FoodTruck.shared.refrigerator.lightState, .on)
  }

  func testLightGoesOut() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    try FoodTruck.shared.refrigerator.closeDoor()
    XCTAssertEqual(FoodTruck.shared.refrigerator.lightState, .off)
  }
}

// After
@Suite(.serialized)
class RefrigeratorTests {
  @Test func lightComesOn() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    #expect(FoodTruck.shared.refrigerator.lightState == .on)
  }

  @Test func lightGoesOut() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    try FoodTruck.shared.refrigerator.closeDoor()
    #expect(FoodTruck.shared.refrigerator.lightState == .off)
  }
}

For more information, see Running tests serially or in parallel.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

API Reference\ Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

API Reference\ Known issues

Highlight known issues when running tests.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Migrating a test from XCTest

TestTrait Protocol

Skip Navigation

Protocol

TestTrait

A protocol describing a trait that you can add to a test function.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol TestTrait : Trait

The testing library defines a number of traits that you can add to test functions. You can also define your own traits by creating types that conform to this protocol, or to the SuiteTrait protocol.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is TestTrait

Parallelization Trait

Skip Navigation

Structure

ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ParallelizationTrait

When you add this trait to a parameterized test function, that test runs its cases serially instead of in parallel. This trait has no effect when you apply it to a non-parameterized test function.

When you add this trait to a test suite, that suite runs its contained test functions (including their cases, when parameterized) and sub-suites serially instead of in parallel. If the sub-suites have children, they also run serially.

This trait does not affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if you disable test parallelization globally (for example, by passing --no-parallel to the swift test command.)

To add this trait to a test, use serialized.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ParallelizationTrait

Test Execution Control

Skip Navigation

Article

Running tests serially or in parallel

Control whether tests run serially or in parallel.

By default, tests run in parallel with respect to each other. Parallelization is accomplished by the testing library using task groups, and tests generally all run in the same process. The number of tests that run concurrently is controlled by the Swift runtime.

Parallelization can be disabled on a per-function or per-suite basis using the serialized trait:

@Test(.serialized, arguments: Food.allCases) func prepare(food: Food) {
  // This function will be invoked serially, once per food, because it has the
  // .serialized trait.
}

@Suite(.serialized) struct FoodTruckTests {
  @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) {
    // This function will be invoked serially, once per condiment, because the
    // containing suite has the .serialized trait.
  }

  @Test func startEngine() async throws {
    // This function will not run while refill(condiment:) is running. One test
    // must end before the other will start.
  }
}

When added to a parameterized test function, this trait causes that test to run its cases serially instead of in parallel. When applied to a non-parameterized test function, this trait has no effect. When applied to a test suite, this trait causes that suite to run its contained test functions and sub-suites serially instead of in parallel.

This trait is recursively applied: if it is applied to a suite, any parameterized tests or test suites contained in that suite are also serialized (as are any tests contained in those suites, and so on.)

This trait doesn’t affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if test parallelization is globally disabled (by, for example, passing --no-parallel to the swift test command.)

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Current page is Running tests serially or in parallel

Enabling Tests

Skip Navigation

Article

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Often, a test is only applicable in specific circumstances. For instance, you might want to write a test that only runs on devices with particular hardware capabilities, or performs locale-dependent operations. The testing library allows you to add traits to your tests that cause runners to automatically skip them if conditions like these are not met.

If you need to disable a test unconditionally, use the disabled(_:sourceLocation:) function. Given the following test function:

@Test("Food truck sells burritos")
func sellsBurritos() async throws { ... }

Add the trait after the test’s display name:

@Test("Food truck sells burritos", .disabled())
func sellsBurritos() async throws { ... }

The test will now always be skipped.

It’s also possible to add a comment to the trait to present in the output from the runner when it skips the test:

@Test("Food truck sells burritos", .disabled("We only sell Thai cuisine"))
func sellsBurritos() async throws { ... }

Sometimes, it makes sense to enable a test only when a certain condition is met. Consider the following test function:

@Test("Ice cream is cold")
func isCold() async throws { ... }

If it’s currently winter, then presumably ice cream won’t be available for sale and this test will fail. It therefore makes sense to only enable it if it’s currently summer. You can conditionally enable a test with enabled(if:_:sourceLocation:):

@Test("Ice cream is cold", .enabled(if: Season.current == .summer))
func isCold() async throws { ... }

It’s also possible to conditionally disable a test and to combine multiple conditions:

@Test(
  "Ice cream is cold",
  .enabled(if: Season.current == .summer),
  .disabled("We ran out of sprinkles")
)
func isCold() async throws { ... }

If a test is disabled because of a problem for which there is a corresponding bug report, you can use one of these functions to show the relationship between the test and the bug report:

For example, the following test cannot run due to bug number "12345":

@Test(
  "Ice cream is cold",
  .enabled(if: Season.current == .summer),
  .disabled("We ran out of sprinkles"),
  .bug(id: "12345")
)
func isCold() async throws { ... }

If a test has multiple conditions applied to it, they must all pass for it to run. Otherwise, the test notes the first condition to fail as the reason the test is skipped.

If a condition is complex, consider factoring it out into a helper function to improve readability:

func allIngredientsAvailable(for food: Food) -> Bool { ... }

@Test(
  "Can make sundaes",
  .enabled(if: Season.current == .summer),
  .enabled(if: allIngredientsAvailable(for: .sundae))
)
func makeSundae() async throws { ... }

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is Enabling and disabling tests

Testing Expectations

Skip Navigation

Collection

API Collection

Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

Use expect(_:_:sourceLocation:) and require(_:_:sourceLocation:) macros to validate expected outcomes. To validate that an error is thrown, or not thrown, the testing library provides several overloads of the macros that you can use. For more information, see Testing for errors in Swift code.

Use a Confirmation to confirm the occurrence of an asynchronous event that you can’t check directly using an expectation. For more information, see Testing asynchronous code.

To validate that your code produces an expected value, use expect(_:_:sourceLocation:). This macro captures the expression you pass, and provides detailed information when the code doesn’t satisfy the expectation.

@Test func calculatingOrderTotal() {
  let calculator = OrderCalculator()
  #expect(calculator.total(of: [3, 3]) == 7)
  // Prints "Expectation failed: (calculator.total(of: [3, 3]) → 6) == 7"
}

Your test keeps running after expect(_:_:sourceLocation:) fails. To stop the test when the code doesn’t satisfy a requirement, use require(_:_:sourceLocation:) instead:

@Test func returningCustomerRemembersUsualOrder() throws {
  let customer = try #require(Customer(id: 123))
  // The test runner doesn't reach this line if the customer is nil.
  #expect(customer.usualOrder.countOfItems == 2)
}

require(_:_:sourceLocation:) throws an instance of ExpectationFailedError when your code fails to satisfy the requirement.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Testing for errors in Swift code

Ensure that your code handles errors in the way you expect.

macro expect<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?

Check that an expression always throws an error of a given type.

macro expect<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?

Check that an expression always throws a specific error.

macro expect<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> (any Error)?

Check that an expression always throws an error matching some condition.

Deprecated

macro require<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E

Check that an expression always throws an error of a given type, and throw an error if it does not.

macro require<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E

macro require<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> any Error

Check that an expression always throws an error matching some condition, and throw an error if it does not.

Deprecated

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

struct Expectation

A type describing an expectation that has been evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

struct SourceLocation

A type representing a location in source code.

API Reference\ Known issues

Highlight known issues when running tests.

Current page is Expectations and confirmations

Known Issue Matcher

Skip Navigation

Type Alias

KnownIssueMatcher

A function that is used to match known issues.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

typealias KnownIssueMatcher = (Issue) -> Bool

issue

The issue to match.

Whether or not issue is known to occur.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void)

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void, when: () -> Bool, matching: KnownIssueMatcher) rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

Current page is KnownIssueMatcher

Associating Bugs with Tests

Skip Navigation

Article

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Tests allow developers to prove that the code they write is working as expected. If code isn’t working correctly, bug trackers are often used to track the work necessary to fix the underlying problem. It’s often useful to associate specific bugs with tests that reproduce them or verify they are fixed.

To associate a bug with a test, use one of these functions:

The first argument to these functions is a URL representing the bug in its bug-tracking system:

@Test("Food truck engine works", .bug("https://www.example.com/issues/12345"))
func engineWorks() async {
  var foodTruck = FoodTruck()
  await foodTruck.engine.start()
  #expect(foodTruck.engine.isRunning)
}

You can also specify the bug’s unique identifier in its bug-tracking system in addition to, or instead of, its URL:

@Test(
  "Food truck engine works",
  .bug(id: "12345"),
  .bug("https://www.example.com/issues/67890", id: 67890)
)
func engineWorks() async {
  var foodTruck = FoodTruck()
  await foodTruck.engine.start()
  #expect(foodTruck.engine.isRunning)
}

A bug’s URL is passed as a string and must be parseable according to RFC 3986. A bug’s unique identifier can be passed as an integer or as a string. For more information on the formats recognized by the testing library, see Interpreting bug identifiers.

A bug’s unique identifier or URL may be insufficient to uniquely and clearly identify a bug associated with a test. Bug trackers universally provide a “title” field for bugs that is not visible to the testing library. To add a bug’s title to a test, include it after the bug’s unique identifier or URL:

@Test(
  "Food truck has napkins",
  .bug(id: "12345", "Forgot to buy more napkins")
)
func hasNapkins() async {
  ...
}

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Associating bugs with tests

Test Comment Structure

Skip Navigation

Structure

Comment

A type that represents a comment related to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Comment

Use this type to provide context or background information about a test’s purpose, explain how a complex test operates, or include details which may be helpful when diagnosing issues recorded by a test.

To add a comment to a test or suite, add a code comment before its @Test or @Suite attribute. See Adding comments to tests for more details.

init(rawValue: String)

Creates a new instance with the specified raw value.

var rawValue: String

The single comment string that this comment contains.

typealias RawValue

The raw type that can be used to represent all values of the conforming type.

API Reference\ CustomStringConvertible Implementations

API Reference\ Equatable Implementations

API Reference\ ExpressibleByExtendedGraphemeClusterLiteral Implementations

API Reference\ ExpressibleByStringInterpolation Implementations

API Reference\ ExpressibleByStringLiteral Implementations

API Reference\ ExpressibleByUnicodeScalarLiteral Implementations

API Reference\ RawRepresentable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Comment

Swift Test Time Limit

Skip Navigation

Instance Property

timeLimit

The maximum amount of time this test’s cases may run for.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var timeLimit: Duration? { get }

Associate a time limit with tests by using timeLimit(_:).

If a test has more than one time limit associated with it, the value of this property is the shortest one. If a test has no time limits associated with it, the value of this property is nil.

Current page is timeLimit

Swift fileID Property

Skip Navigation

Instance Property

fileID

The file ID of the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var fileID: String { get set }

var moduleName: String

The name of the module containing the source file.

var fileName: String

The name of the source file.

Current page is fileID

Tag() Macro

Skip Navigation

Macro

Tag()

Declare a tag that can be applied to a test function or test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(accessor) @attached(peer)
macro Tag()

Adding tags to tests

Use this tag with members of the Tag type declared in an extension to mark them as usable with tests. For more information on declaring tags, see Adding tags to tests.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Tag()

Swift Testing Error

Skip Navigation

Instance Property

error

The error which was associated with this issue, if any.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var error: (any Error)? { get }

The value of this property is non- nil when kind is Issue.Kind.errorCaught(_:).

Current page is error

Test Description Property

Skip Navigation

Instance Property

testDescription

A description of this instance to use when presenting it in a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var testDescription: String { get }

Required Default implementation provided.

Do not use this property directly. To get the test description of a value, use Swift/String/init(describingForTest:).

var testDescription: String

A description of this instance to use when presenting it in a test’s output.

Current page is testDescription

Source Location Trait

Skip Navigation

Instance Property

sourceLocation

The source location where this trait is specified.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation

Current page is sourceLocation

Swift Testing Name Property

Skip Navigation

Instance Property

name

The name of this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var name: String

The value of this property is equal to the name of the symbol to which the Test attribute is applied (that is, the name of the type or function.) To get the customized display name specified as part of the Test attribute, use the displayName property.

Current page is name

isRecursive Trait

Skip Navigation

Instance Property

isRecursive

Whether this instance should be applied recursively to child test suites and test functions.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isRecursive: Bool { get }

Required Default implementation provided.

If the value is true, then the testing library applies this trait recursively to child test suites and test functions. Otherwise, it only applies the trait to the test suite to which you added the trait.

By default, traits are not recursively applied to children.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

Current page is isRecursive

Swift fileName Property

Skip Navigation

Instance Property

fileName

The name of the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var fileName: String { get }

The name of the source file is derived from this instance’s fileID property. It consists of the substring of the file ID after the last forward-slash character ( "/".) For example, if the value of this instance’s fileID property is "FoodTruck/WheelTests.swift", the file name is "WheelTests.swift".

The structure of file IDs is described in the documentation for #fileID in the Swift standard library.

var fileID: String

The file ID of the source file.

var moduleName: String

The name of the module containing the source file.

Current page is fileName

Developer Comments Management

Skip Navigation

Instance Property

comments

Any comments provided by the developer and associated with this issue.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment]

If no comment was supplied when the issue occurred, the value of this property is the empty array.

Current page is comments

Source Location in Testing

Skip Navigation

Instance Property

sourceLocation

The location in source where this issue occurred, if available.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation? { get set }

Current page is sourceLocation

Test Comments

Skip Navigation

Instance Property

comments

The complete set of comments about this test from all of its traits.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment] { get }

Current page is comments

Test Duration Type

Skip Navigation

Structure

TimeLimitTrait.Duration

A type representing the duration of a time limit applied to a test.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

struct Duration

Use this type to specify a test timeout with TimeLimitTrait. TimeLimitTrait uses this type instead of Swift’s built-in Duration type because the testing library doesn’t support high-precision, arbitrarily short durations for test timeouts. The smallest unit of time you can specify in a Duration is minutes.

static func minutes(some BinaryInteger) -> TimeLimitTrait.Duration

Construct a time limit duration given a number of minutes.

Current page is TimeLimitTrait.Duration

Test Tags Overview

Skip Navigation

Instance Property

tags

The complete, unique set of tags associated with this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var tags: Set<Tag> { get }

Tags are associated with tests using the tags(_:) function.

Current page is tags

Customizing Display Names

Skip Navigation

Instance Property

displayName

The customized display name of this instance, if specified.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var displayName: String?

Current page is displayName

Serialized Trait

Skip Navigation

Type Property

serialized

A trait that serializes the test to which it is applied.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static var serialized: ParallelizationTrait { get }

Available when Self is ParallelizationTrait.

Migrating a test from XCTest

Running tests serially or in parallel

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

Running tests serially or in parallel

Control whether tests run serially or in parallel.

Current page is serialized

Swift Test Source Location

Skip Navigation

Instance Property

sourceLocation

The source location of this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation

Current page is sourceLocation

Test Case Overview

Skip Navigation

Structure

Test.Case

A single test case from a parameterized Test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Case

A test case represents a test run with a particular combination of inputs. Tests that are not parameterized map to a single instance of Test.Case.

var isParameterized: Bool

Whether or not this test case is from a parameterized test.

static var current: Test.Case?

The test case that is running on the current task, if any.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

Current page is Test.Case

Tag List Overview

Skip Navigation

Structure

Tag.List

A type representing one or more tags applied to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct List

To add this trait to a test, use the tags(_:) function.

var tags: [Tag]

The list of tags contained in this instance.

API Reference\ CustomStringConvertible Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Tag.List

Test Suite Indicator

Skip Navigation

Instance Property

isSuite

Whether or not this instance is a test suite containing other tests.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isSuite: Bool { get }

Instances of Test attached to types rather than functions are test suites. They do not contain any test logic of their own, but they may have traits added to them that also apply to their subtests.

A test suite can be declared using the Suite(_:_:) macro.

Current page is isSuite

Swift moduleName Property

Skip Navigation

Instance Property

moduleName

The name of the module containing the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var moduleName: String { get }

The name of the module is derived from this instance’s fileID property. It consists of the substring of the file ID up to the first forward-slash character ( "/".) For example, if the value of this instance’s fileID property is "FoodTruck/WheelTests.swift", the module name is "FoodTruck".

The structure of file IDs is described in the documentation for the #fileID macro in the Swift standard library.

var fileID: String

The file ID of the source file.

var fileName: String

The name of the source file.

#fileID

Current page is moduleName

Swift Testing Comments

Skip Navigation

Instance Property

comments

The user-provided comments for this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment] { get }

The default value of this property is an empty array.

Current page is comments

Associated Bugs in Testing

Skip Navigation

Instance Property

associatedBugs

The set of bugs associated with this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var associatedBugs: [Bug] { get }

For information on how to associate a bug with a test, see the documentation for Bug.

Current page is associatedBugs

Expectation Requirement

Skip Navigation

Instance Property

isRequired

Whether or not the expectation was required to pass.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isRequired: Bool

Current page is isRequired

Testing Asynchronous Code

Skip Navigation

Article

Testing asynchronous code

Validate whether your code causes expected events to happen.

The testing library integrates with Swift concurrency, meaning that in many situations you can test asynchronous code using standard Swift features. Mark your test function as async and, in the function body, await any asynchronous interactions:

@Test func priceLookupYieldsExpectedValue() async {
  let mozarellaPrice = await unitPrice(for: .mozarella)
  #expect(mozarellaPrice == 3)
}

In more complex situations you can use Confirmation to discover whether an expected event happens.

Call confirmation(_:expectedCount:isolation:sourceLocation:_:) in your asynchronous test function to create a Confirmation for the expected event. In the trailing closure parameter, call the code under test. Swift Testing passes a Confirmation as the parameter to the closure, which you call as a function in the event handler for the code under test when the event you’re testing for occurs:

@Test("OrderCalculator successfully calculates subtotal for no pizzas")
func subtotalForNoPizzas() async {
  let calculator = OrderCalculator()
  await confirmation() { confirmation in
    calculator.successHandler = { _ in confirmation() }
    _ = await calculator.subtotal(for: PizzaToppings(bases: []))
  }
}

If you expect the event to happen more than once, set the expectedCount parameter to the number of expected occurrences. The test passes if the number of occurrences during the test matches the expected count, and fails otherwise.

You can also pass a range to confirmation(_:expectedCount:isolation:sourceLocation:_:) if the exact number of times the event occurs may change over time or is random:

@Test("Customers bought sandwiches")
func boughtSandwiches() async {
  await confirmation(expectedCount: 0 ..< 1000) { boughtSandwich in
    var foodTruck = FoodTruck()
    foodTruck.orderHandler = { order in
      if order.contains(.sandwich) {
        boughtSandwich()
      }
    }
    await FoodTruck.operate()
  }
}

In this example, there may be zero customers or up to (but not including) 1,000 customers who order sandwiches. Any range expression which includes an explicit lower bound can be used:

Range Expression Usage
1... If an event must occur at least once
5... If an event must occur at least five times
1 ... 5 If an event must occur at least once, but not more than five times
0 ..< 100 If an event may or may not occur, but must not occur more than 99 times

To validate that a particular event doesn’t occur during a test, create a Confirmation with an expected count of 0:

@Test func orderCalculatorEncountersNoErrors() async {
  let calculator = OrderCalculator()
  await confirmation(expectedCount: 0) { confirmation in
    calculator.errorHandler = { _ in confirmation() }
    calculator.subtotal(for: PizzaToppings(bases: []))
  }
}

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

Current page is Testing asynchronous code

Swift Testing Tags

Skip Navigation

Instance Property

tags

The list of tags contained in this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var tags: [Tag]

This preserves the list of the tags exactly as they were originally specified, in their original order, including duplicate entries. To access the complete, unique set of tags applied to a Test, see tags.

Current page is tags

Current Test Case

Skip Navigation

Type Property

current

The test case that is running on the current task, if any.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static var current: Test.Case? { get }

If the current task is running a test, or is a subtask of another task that is running a test, the value of this property describes the test’s currently-running case. If no test is currently running, the value of this property is nil.

If the current task is detached from a task that started running a test, or if the current thread was created without using Swift concurrency (e.g. by using Thread.detachNewThread(_:) or DispatchQueue.async(execute:)), the value of this property may be nil.

Current page is current

Parallelization Trait

Skip Navigation

Structure

ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ParallelizationTrait

When you add this trait to a parameterized test function, that test runs its cases serially instead of in parallel. This trait has no effect when you apply it to a non-parameterized test function.

When you add this trait to a test suite, that suite runs its contained test functions (including their cases, when parameterized) and sub-suites serially instead of in parallel. If the sub-suites have children, they also run serially.

This trait does not affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if you disable test parallelization globally (for example, by passing --no-parallel to the swift test command.)

To add this trait to a test, use serialized.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ParallelizationTrait

Condition Trait Overview

Skip Navigation

Structure

ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ConditionTrait

Migrating a test from XCTest

To add this trait to a test, use one of the following functions:

var comments: [Comment]

The user-provided comments for this trait.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var sourceLocation: SourceLocation

The source location where this trait is specified.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ConditionTrait

TestScopeProvider Overview

Skip Navigation

Type Alias

Comment.TestScopeProvider

The type of the test scope provider for this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

typealias TestScopeProvider = Never

The default type is Never, which can’t be instantiated. The scopeProvider(for:testCase:)-cjmg method for any trait with Never as its test scope provider type must return nil, meaning that the trait doesn’t provide a custom scope for tests it’s applied to.

Current page is Comment.TestScopeProvider

Bug Identifier Overview

Skip Navigation

Instance Property

id

A unique identifier in this bug’s associated bug-tracking system, if available.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var id: String?

For more information on how the testing library interprets bug identifiers, see Interpreting bug identifiers.

Current page is id

TestScopeProvider Overview

Skip Navigation

Type Alias

TimeLimitTrait.TestScopeProvider

The type of the test scope provider for this trait.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

typealias TestScopeProvider = Never

The default type is Never, which can’t be instantiated. The scopeProvider(for:testCase:)-cjmg method for any trait with Never as its test scope provider type must return nil, meaning that the trait doesn’t provide a custom scope for tests it’s applied to.

Current page is TimeLimitTrait.TestScopeProvider

Test Duration Limit

Skip Navigation

Instance Property

timeLimit

The maximum amount of time a test may run for before timing out.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var timeLimit: Duration

Current page is timeLimit

Swift Issue Kind

Skip Navigation

Instance Property

kind

The kind of issue this value represents.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var kind: Issue.Kind

Current page is kind

Time Limit Trait

Skip Navigation

Type Method

timeLimit(_:)

Construct a time limit trait that causes a test to time out if it runs for too long.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

static func timeLimit(_ timeLimit: TimeLimitTrait.Duration) -> Self

Available when Self is TimeLimitTrait.

timeLimit

The maximum amount of time the test may run for.

An instance of TimeLimitTrait.

Limiting the running time of tests

Test timeouts do not support high-precision, arbitrarily short durations due to variability in testing environments. You express the duration in minutes, with a minimum duration of one minute.

When you associate this trait with a test, that test must complete within a time limit of, at most, timeLimit. If the test runs longer, the testing library records a Issue.Kind.timeLimitExceeded(timeLimitComponents:) issue, which it treats as a test failure.

The testing library can use a shorter time limit than that specified by timeLimit if you configure it to enforce a maximum per-test limit. When you configure a maximum per-test limit, the time limit of the test this trait is applied to is the shorter of timeLimit and the maximum per-test limit. For information on configuring maximum per-test limits, consult the documentation for the tool you use to run your tests.

If a test is parameterized, this time limit is applied to each of its test cases individually. If a test has more than one time limit associated with it, the testing library uses the shortest time limit.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

Current page is timeLimit(_:)

Swift Testing Comment

Skip Navigation

Instance Property

rawValue

The single comment string that this comment contains.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var rawValue: String

To get the complete set of comments applied to a test, see comments.

Current page is rawValue

isRecursive Property Overview

Skip Navigation

Instance Property

isRecursive

Whether this instance should be applied recursively to child test suites and test functions.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var isRecursive: Bool { get }

If the value is true, then the testing library applies this trait recursively to child test suites and test functions. Otherwise, it only applies the trait to the test suite to which you added the trait.

By default, traits are not recursively applied to children.

Current page is isRecursive

Test Preparation Method

Skip Navigation

Instance Method

prepare(for:)

Prepare to run the test that has this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func prepare(for test: Test) async throws

test

The test that has this trait.

The testing library calls this method after it discovers all tests and their traits, and before it begins to run any tests. Use this method to prepare necessary internal state, or to determine whether the test should run.

The default implementation of this method does nothing.

Current page is prepare(for:)

Test Preparation Method

Skip Navigation

Instance Method

prepare(for:)

Prepare to run the test that has this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func prepare(for test: Test) async throws

Required Default implementation provided.

test

The test that has this trait.

The testing library calls this method after it discovers all tests and their traits, and before it begins to run any tests. Use this method to prepare necessary internal state, or to determine whether the test should run.

The default implementation of this method does nothing.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self.TestScopeProvider?

Get this trait’s scope provider for the specified test and optional test case.

Required Default implementations provided.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

Current page is prepare(for:)

Swift Testing Tags

Skip Navigation

Type Method

tags(_:)

Construct a list of tags to apply to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func tags(_ tags: Tag...) -> Self

Available when Self is Tag.List.

tags

The list of tags to apply to the test.

An instance of Tag.List containing the specified tags.

Organizing test functions with suite types

Defining test functions

Adding tags to tests

var comments: [Comment]

The user-provided comments for this trait.

Required Default implementation provided.

Current page is tags(_:)

Swift Testing ID

Skip Navigation

Instance Property

id

The stable identity of the entity associated with this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var id: Test.ID { get }

Current page is id

Swift Test Description

Skip Navigation

Instance Property

testDescription

A description of this instance to use when presenting it in a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var testDescription: String { get }

Available when Self conforms to StringProtocol.

Do not use this property directly. To get the test description of a value, use Swift/String/init(describingForTest:).

Current page is testDescription

Bug Tracking Method

Skip Navigation

Type Method

bug(_:_:)

Constructs a bug to track with a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func bug(
    _ url: String,
    _ title: Comment? = nil
) -> Self

Available when Self is Bug.

url

A URL that refers to this bug in the associated bug-tracking system.

title

Optionally, the human-readable title of the bug.

An instance of Bug that represents the specified bug.

Associating bugs with tests

Enabling and disabling tests

Interpreting bug identifiers

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is bug(_:_:)

Record Test Issues

Skip Navigation

Type Method

record(_:sourceLocation:)

Record an issue when a running test fails unexpectedly.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@discardableResult
static func record(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Issue

comment

A comment describing the expectation.

sourceLocation

The source location to which the issue should be attributed.

The issue that was recorded.

Migrating a test from XCTest

Use this function if, while running a test, an issue occurs that cannot be represented as an expectation (using the expect(_:_:sourceLocation:) or require(_:_:sourceLocation:) macros.)

Current page is record(_:sourceLocation:)

Scope Provider Method

Skip Navigation

Instance Method

scopeProvider(for:testCase:)

Get this trait’s scope provider for the specified test and optional test case.

Swift 6.1+Xcode 16.3+

func scopeProvider(
    for test: Test,
    testCase: Test.Case?
) -> Self.TestScopeProvider?

Required Default implementations provided.

test

The test for which a scope provider is being requested.

testCase

The test case for which a scope provider is being requested, if any. When test represents a suite, the value of this argument is nil.

A value conforming to TestScopeProvider which you use to provide custom scoping for test or testCase. Returns nil if the trait doesn’t provide any custom scope for the test or test case.

If this trait’s type conforms to TestScoping, the default value returned by this method depends on the values of test and testCase:

  • If test represents a suite, this trait must conform to SuiteTrait. If the value of this suite trait’s isRecursive property is true, then this method returns nil, and the suite trait provides its custom scope once for each test function the test suite contains. If the value of isRecursive is false, this method returns self, and the suite trait provides its custom scope once for the entire test suite.

  • If test represents a test function, this trait also conforms to TestTrait. If testCase is nil, this method returns nil; otherwise, it returns self. This means that by default, a trait which is applied to or inherited by a test function provides its custom scope once for each of that function’s cases.

A trait may override this method to further customize the default behaviors above. For example, if a trait needs to provide custom test scope both once per-suite and once per-test function in that suite, it implements the method to return a non- nil scope provider under those conditions.

A trait may also implement this method and return nil if it determines that it does not need to provide a custom scope for a particular test at runtime, even if the test has the trait applied. This can improve performance and make diagnostics clearer by avoiding an unnecessary call to provideScope(for:testCase:performing:).

If this trait’s type does not conform to TestScoping and its associated TestScopeProvider type is the default Never, then this method returns nil by default. This means that instances of this trait don’t provide a custom scope for tests to which they’re applied.

func scopeProvider(for: Test, testCase: Test.Case?) -> Never?

Get this trait’s scope provider for the specified test or test case.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self?

Get this trait’s scope provider for the specified test or test case.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self?

Get this trait’s scope provider for the specified test and optional test case.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

Required Default implementation provided.

Current page is scopeProvider(for:testCase:)

Swift Testing Expectation

Skip Navigation

Macro

expect(_:_:sourceLocation:)

Check that an expectation has passed after a condition has been evaluated.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro expect(
    _ condition: Bool,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
)

condition

The condition to be evaluated.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

Testing for errors in Swift code

Migrating a test from XCTest

If condition evaluates to false, an Issue is recorded for the test that is running in the current task.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Current page is expect(_:_:sourceLocation:)

System Issue Kind

Skip Navigation

Case

Issue.Kind.system

An issue due to a failure in the underlying system, not due to a failure within the tests being run.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

case system

Current page is Issue.Kind.system

Disable Test Condition

Skip Navigation

Type Method

disabled(_:sourceLocation:)

Constructs a condition trait that disables a test unconditionally.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that always disables the test to which it is added.

Enabling and disabling tests

Organizing test functions with suite types

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(_:sourceLocation:)

Hashing Method

Skip Navigation

Instance Method

hash(into:)

Hashes the essential components of this value by feeding them into the given hasher.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func hash(into hasher: inout Hasher)

hasher

The hasher to use when combining the components of this instance.

Implement this method to conform to the Hashable protocol. The components used for hashing must be the same as the components compared in your type’s == operator implementation. Call hasher.combine(_:) with each of these components.

Current page is hash(into:)

Tag Comparison Operator

Skip Navigation

Operator

<(_:_:)

Returns a Boolean value indicating whether the value of the first argument is less than that of the second argument.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func < (lhs: Tag, rhs: Tag) -> Bool

lhs

A value to compare.

rhs

Another value to compare.

This function is the only requirement of the Comparable protocol. The remainder of the relational operator functions are implemented by the standard library for any type that conforms to Comparable.

Current page is <(_:_:)

Test Execution Control

Skip Navigation

Article

Running tests serially or in parallel

Control whether tests run serially or in parallel.

By default, tests run in parallel with respect to each other. Parallelization is accomplished by the testing library using task groups, and tests generally all run in the same process. The number of tests that run concurrently is controlled by the Swift runtime.

Parallelization can be disabled on a per-function or per-suite basis using the serialized trait:

@Test(.serialized, arguments: Food.allCases) func prepare(food: Food) {
  // This function will be invoked serially, once per food, because it has the
  // .serialized trait.
}

@Suite(.serialized) struct FoodTruckTests {
  @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) {
    // This function will be invoked serially, once per condiment, because the
    // containing suite has the .serialized trait.
  }

  @Test func startEngine() async throws {
    // This function will not run while refill(condiment:) is running. One test
    // must end before the other will start.
  }
}

When added to a parameterized test function, this trait causes that test to run its cases serially instead of in parallel. When applied to a non-parameterized test function, this trait has no effect. When applied to a test suite, this trait causes that suite to run its contained test functions and sub-suites serially instead of in parallel.

This trait is recursively applied: if it is applied to a suite, any parameterized tests or test suites contained in that suite are also serialized (as are any tests contained in those suites, and so on.)

This trait doesn’t affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if test parallelization is globally disabled (by, for example, passing --no-parallel to the swift test command.)

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Current page is Running tests serially or in parallel

Scope Provider Method

Skip Navigation

Instance Method

scopeProvider(for:testCase:)

Get this trait’s scope provider for the specified test or test case.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func scopeProvider(
    for test: Test,
    testCase: Test.Case?
) -> Never?

Available when TestScopeProvider is Never.

test

The test for which the testing library requests a scope provider.

testCase

The test case for which the testing library requests a scope provider, if any. When test represents a suite, the value of this argument is nil.

The testing library uses this implementation of scopeProvider(for:testCase:) when the trait type’s associated TestScopeProvider type is Never.

Current page is scopeProvider(for:testCase:)

Swift Test Issues

Skip Navigation

Structure

Issue

A type describing a failure or warning which occurred during a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Issue

Associating bugs with tests

Interpreting bug identifiers

var comments: [Comment]

Any comments provided by the developer and associated with this issue.

var error: (any Error)?

The error which was associated with this issue, if any.

var kind: Issue.Kind

The kind of issue this value represents.

var sourceLocation: SourceLocation?

The location in source where this issue occurred, if available.

static func record(any Error, Comment?, sourceLocation: SourceLocation) -> Issue

Record a new issue when a running test unexpectedly catches an error.

static func record(Comment?, sourceLocation: SourceLocation) -> Issue

Record an issue when a running test fails unexpectedly.

enum Kind

Kinds of issues which may be recorded.

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

Current page is Issue

Confirmation Testing

Skip Navigation

Structure

Confirmation

A type that can be used to confirm that an event occurs zero or more times.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Confirmation

Testing asynchronous code

Migrating a test from XCTest

func callAsFunction(count: Int)

Confirm this confirmation.

func confirm(count: Int)

Confirm this confirmation.

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

Current page is Confirmation

Parameterized Test Macro

Skip Navigation

Macro

Test(_:_:arguments:)

Declare a test parameterized over two zipped collections of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C1, C2>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments zippedCollections: Zip2Sequence<C1, C2>
) where C1 : Collection, C1 : Sendable, C2 : Collection, C2 : Sendable, C1.Element : Sendable, C2.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

zippedCollections

Two zipped collections of values to pass to testFunction.

During testing, the associated test function is called once for each element in zippedCollections.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:)

Known Issue Function

Skip Navigation

  • Swift Testing
  • withKnownIssue(_:isIntermittent:sourceLocation:_:)

Function

withKnownIssue(_:isIntermittent:sourceLocation:_:)

Invoke a function that has a known issue that is expected to occur during its execution.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func withKnownIssue(
    _ comment: Comment? = nil,
    isIntermittent: Bool = false,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: () throws -> Void
)

comment

An optional comment describing the known issue.

isIntermittent

Whether or not the known issue occurs intermittently. If this argument is true and the known issue does not occur, no secondary issue is recorded.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

Migrating a test from XCTest

Use this function when a test is known to raise one or more issues that should not cause the test to fail. For example:

@Test func example() {
  withKnownIssue {
    try flakyCall()
  }
}

Because all errors thrown by body are caught as known issues, this function is not throwing. If only some errors or issues are known to occur while others should continue to cause test failures, use withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:) instead.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void, when: () -> Bool, matching: KnownIssueMatcher) rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

typealias KnownIssueMatcher

A function that is used to match known issues.

Current page is withKnownIssue(_:isIntermittent:sourceLocation:_:)

Event Confirmation Function

Skip Navigation

Function

confirmation(_:expectedCount:sourceLocation:_:)

Confirm that some event occurs during the invocation of a function.

Swift 6.0+Xcode 16.0+

func confirmation<R>(
    _ comment: Comment? = nil,
    expectedCount: Int = 1,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: (Confirmation) async throws -> R
) async rethrows -> R

comment

An optional comment to apply to any issues generated by this function.

expectedCount

The number of times the expected event should occur when body is invoked. The default value of this argument is 1, indicating that the event should occur exactly once. Pass 0 if the event should never occur when body is invoked.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

Whatever is returned by body.

Migrating a test from XCTest

Testing asynchronous code

Use confirmations to check that an event occurs while a test is running in complex scenarios where #expect() and #require() are insufficient. For example, a confirmation may be useful when an expected event occurs:

  • In a context that cannot be awaited by the calling function such as an event handler or delegate callback;

  • More than once, or never; or

  • As a callback that is invoked as part of a larger operation.

To use a confirmation, pass a closure containing the work to be performed. The testing library will then pass an instance of Confirmation to the closure. Every time the event in question occurs, the closure should call the confirmation:

let n = 10
await confirmation("Baked buns", expectedCount: n) { bunBaked in
  foodTruck.eventHandler = { event in
    if event == .baked(.cinnamonBun) {
      bunBaked()
    }
  }
  await foodTruck.bake(.cinnamonBun, count: n)
}

When the closure returns, the testing library checks if the confirmation’s preconditions have been met, and records an issue if they have not.

Testing asynchronous code

Validate whether your code causes expected events to happen.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

Current page is confirmation(_:expectedCount:sourceLocation:_:)

Disable Test Trait

Skip Navigation

Type Method

disabled(_:sourceLocation:_:)

Constructs a condition trait that disables a test if its value is true.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ condition: @escaping () async throws -> Bool
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns false, the trait allows the test to run. Otherwise, the testing library skips the test.

An instance of ConditionTrait that evaluates the specified closure.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(_:sourceLocation:_:)

Test Disabling Trait

Skip Navigation

Type Method

disabled(if:_:sourceLocation:)

Constructs a condition trait that disables a test if its value is true.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    if condition: @autoclosure @escaping () throws -> Bool,
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns false, the trait allows the test to run. Otherwise, the testing library skips the test.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that evaluates the closure you provide.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(if:_:sourceLocation:)

Condition Trait Management

Skip Navigation

Type Method

enabled(if:_:sourceLocation:)

Constructs a condition trait that disables a test if it returns false.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func enabled(
    if condition: @autoclosure @escaping () throws -> Bool,
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns true, the trait allows the test to run. Otherwise, the testing library skips the test.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that evaluates the closure you provide.

Enabling and disabling tests

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is enabled(if:_:sourceLocation:)

Swift Testing Macro

Skip Navigation

Macro

require(_:_:sourceLocation:)

Unwrap an optional value or, if it is nil, fail and throw an error.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro require<T>(
    _ optionalValue: T?,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> T

optionalValue

The optional value to be unwrapped.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

The unwrapped value of optionalValue.

Migrating a test from XCTest

If optionalValue is nil, an Issue is recorded for the test that is running in the current task and an instance of ExpectationFailedError is thrown.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

Current page is require(_:_:sourceLocation:)

Parameterized Test Declaration

Skip Navigation

Macro

Test(_:_:arguments:)

Declare a test parameterized over a collection of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments collection: C
) where C : Collection, C : Sendable, C.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

collection

A collection of values to pass to the associated test function.

During testing, the associated test function is called once for each element in collection.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:)

Swift Testing Macro

Skip Navigation

Macro

require(_:_:sourceLocation:)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro require(
    _ condition: Bool,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
)

condition

The condition to be evaluated.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

Migrating a test from XCTest

Testing for errors in Swift code

If condition evaluates to false, an Issue is recorded for the test that is running in the current task and an instance of ExpectationFailedError is thrown.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Current page is require(_:_:sourceLocation:)

Condition Trait Testing

Skip Navigation

Type Method

enabled(_:sourceLocation:_:)

Constructs a condition trait that disables a test if it returns false.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func enabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ condition: @escaping () async throws -> Bool
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns true, the trait allows the test to run. Otherwise, the testing library skips the test.

An instance of ConditionTrait that evaluates the closure you provide.

Current page is enabled(_:sourceLocation:_:)

Known Issue Invocation

Skip Navigation

  • Swift Testing
  • withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Function

withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Invoke a function that has a known issue that is expected to occur during its execution.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func withKnownIssue(
    _ comment: Comment? = nil,
    isIntermittent: Bool = false,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: () throws -> Void,
    when precondition: () -> Bool = { true },
    matching issueMatcher: @escaping KnownIssueMatcher = { _ in true }
) rethrows

comment

An optional comment describing the known issue.

isIntermittent

Whether or not the known issue occurs intermittently. If this argument is true and the known issue does not occur, no secondary issue is recorded.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

precondition

A function that determines if issues are known to occur during the execution of body. If this function returns true, encountered issues that are matched by issueMatcher are considered to be known issues; if this function returns false, issueMatcher is not called and they are treated as unknown.

issueMatcher

A function to invoke when an issue occurs that is used to determine if the issue is known to occur. By default, all issues match.

Migrating a test from XCTest

Use this function when a test is known to raise one or more issues that should not cause the test to fail, or if a precondition affects whether issues are known to occur. For example:

@Test func example() throws {
  try withKnownIssue {
    try flakyCall()
  } when: {
    callsAreFlakyOnThisPlatform()
  } matching: { issue in
    issue.error is FileNotFoundError
  }
}

It is not necessary to specify both precondition and issueMatcher if only one is relevant. If all errors and issues should be considered known issues, use withKnownIssue(_:isIntermittent:sourceLocation:_:) instead.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void)

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

typealias KnownIssueMatcher

A function that is used to match known issues.

Current page is withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Parameterized Testing in Swift

Skip Navigation

Macro

Test(_:_:arguments:_:)

Declare a test parameterized over two collections of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C1, C2>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments collection1: C1,
    _ collection2: C2
) where C1 : Collection, C1 : Sendable, C2 : Collection, C2 : Sendable, C1.Element : Sendable, C2.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

collection1

A collection of values to pass to testFunction.

collection2

A second collection of values to pass to testFunction.

During testing, the associated test function is called once for each pair of elements in collection1 and collection2.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:_:)

Test Declaration Macro

Skip Navigation

Macro

Test(_:_:)

Declare a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test(
    _ displayName: String? = nil,
    _ traits: any TestTrait...
)

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

Defining test functions

Define a test function to validate that code is working correctly.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Test(_:_:)

](https://developer.apple.com/documentation/testing fetched via Firecrawl on June 7, 2025.

Swift Testing Overview

Skip Navigation

Framework

Swift Testing

Create and run tests for your Swift packages and Xcode projects.

Swift 6.0+Xcode 16.0+

The Swift logo on a blue gradient background that contains function, number, tag, and checkmark diamond symbols.

With Swift Testing you leverage powerful and expressive capabilities of the Swift programming language to develop tests with more confidence and less code. The library integrates seamlessly with Swift Package Manager testing workflow, supports flexible test organization, customizable metadata, and scalable test execution.

  • Define test functions almost anywhere with a single attribute.

  • Group related tests into hierarchies using Swift’s type system.

  • Integrate seamlessly with Swift concurrency.

  • Parameterize test functions across wide ranges of inputs.

  • Enable tests dynamically depending on runtime conditions.

  • Parallelize tests in-process.

  • Categorize tests using tags.

  • Associate bugs directly with the tests that verify their fixes or reproduce their problems.

\ \ Meet Swift Testing

\ \ Go further with Swift Testing

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

API Reference\ Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

API Reference\ Known issues

Highlight known issues when running tests.

API Reference\ Traits

Annotate test functions and suites, and customize their behavior.

Current page is Swift Testing

Adding Tags to Tests

Skip Navigation

Article

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

A complex package or project may contain hundreds or thousands of tests and suites. Some subset of those tests may share some common facet, such as being critical or flaky. The testing library includes a type of trait called tags that you can add to group and categorize tests.

Tags are different from test suites: test suites impose structure on test functions at the source level, while tags provide semantic information for a test that can be shared with any number of other tests across test suites, source files, and even test targets.

To add a tag to a test, use the tags(_:) trait. This trait takes a sequence of tags as its argument, and those tags are then applied to the corresponding test at runtime. If any tags are applied to a test suite, then all tests in that suite inherit those tags.

The testing library doesn’t assign any semantic meaning to any tags, nor does the presence or absence of tags affect how the testing library runs tests.

Tags themselves are instances of Tag and expressed as named constants declared as static members of Tag. To declare a named constant tag, use the Tag() macro:

extension Tag {
  @Tag static var legallyRequired: Self
}

@Test("Vendor's license is valid", .tags(.legallyRequired))
func licenseValid() { ... }

If two tags with the same name ( legallyRequired in the above example) are declared in different files, modules, or other contexts, the testing library treats them as equivalent.

If it’s important for a tag to be distinguished from similar tags declared elsewhere in a package or project (or its dependencies), use reverse-DNS naming to create a unique Swift symbol name for your tag:

extension Tag {
  enum com_example_foodtruck {}
}

extension Tag.com_example_foodtruck {
  @Tag static var extraSpecial: Tag
}

@Test(
  "Extra Special Sauce recipe is secret",
  .tags(.com_example_foodtruck.extraSpecial)
)
func secretSauce() { ... }

Tags must always be declared as members of Tag in an extension to that type or in a type nested within Tag. Redeclaring a tag under a second name has no effect and the additional name will not be recognized by the testing library. The following example is unsupported:

extension Tag {
  @Tag static var legallyRequired: Self // ✅ OK: Declaring a new tag.

  static var requiredByLaw: Self { // ❌ ERROR: This tag name isn't
                                   // recognized at runtime.
    legallyRequired
  }
}

If a tag is declared as a named constant outside of an extension to the Tag type (for example, at the root of a file or in another unrelated type declaration), it cannot be applied to test functions or test suites. The following declarations are unsupported:

@Tag let needsKetchup: Self // ❌ ERROR: Tags must be declared in an extension
                            // to Tag.
struct Food {
  @Tag var needsMustard: Self // ❌ ERROR: Tags must be declared in an extension
                              // to Tag.
}

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Adding tags to tests

Swift Test Overview

Skip Navigation

Structure

Test

A type representing a test or suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Test

An instance of this type may represent:

  • A type containing zero or more tests (i.e. a test suite);

  • An individual test function (possibly contained within a type); or

  • A test function parameterized over one or more sequences of inputs.

Two instances of this type are considered to be equal if the values of their id properties are equal.

struct Case

A single test case from a parameterized Test.

var associatedBugs: [Bug]

The set of bugs associated with this test.

var comments: [Comment]

The complete set of comments about this test from all of its traits.

var displayName: String?

The customized display name of this instance, if specified.

var isParameterized: Bool

Whether or not this test is parameterized.

var isSuite: Bool

Whether or not this instance is a test suite containing other tests.

var name: String

The name of this instance.

var sourceLocation: SourceLocation

The source location of this test.

var tags: Set<Tag>

The complete, unique set of tags associated with this test.

var timeLimit: Duration?

The maximum amount of time this test’s cases may run for.

var traits: [any Trait]

The set of traits added to this instance when it was initialized.

static var current: Test?

The test that is running on the current task, if any.

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ Identifiable Implementations

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Test

Adding Comments to Tests

Skip Navigation

Article

Adding comments to tests

Add comments to provide useful information about tests.

It’s often useful to add comments to code to:

  • Provide context or background information about the code’s purpose

  • Explain how complex code implemented

  • Include details which may be helpful when diagnosing issues

Test code is no different and can benefit from explanatory code comments, but often test issues are shown in places where the source code of the test is unavailable such as in continuous integration (CI) interfaces or in log files.

Seeing comments related to tests in these contexts can help diagnose issues more quickly. Comments can be added to test declarations and the testing library will automatically capture and show them when issues are recorded.

To include a comment on a test or suite, write an ordinary Swift code comment immediately before its @Test or @Suite attribute:

// Assumes the standard lunch menu includes a taco
@Test func lunchMenu() {
  let foodTruck = FoodTruck(
    menu: .lunch,
    ingredients: [.tortillas, .cheese]
  )
  #expect(foodTruck.menu.contains { $0 is Taco })
}

The comment, // Assumes the standard lunch menu includes a taco, is added to the test.

The following language comment styles are supported:

Syntax Style
// ... Line comment
/// ... Documentation line comment
/* ... */ Block comment
/** ... */ Documentation block comment

Test comments which are automatically added from source code comments preserve their original formatting, including any prefixes like // or /**. This is because the whitespace and formatting of comments can be meaningful in some circumstances or aid in understanding the comment — for example, when a comment includes an example code snippet or diagram.

As in normal code, comments on tests are generally most useful when they:

  • Add information that isn’t obvious from reading the code

  • Provide useful information about the operation or motivation of a test

If a test is related to a bug or issue, consider using the Bug trait instead of comments. For more information, see Associating bugs with tests.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Adding comments to tests

Organizing Test Functions

Skip Navigation

Article

Organizing test functions with suite types

Organize tests into test suites.

When working with a large selection of test functions, it can be helpful to organize them into test suites.

A test function can be added to a test suite in one of two ways:

  • By placing it in a Swift type.

  • By placing it in a Swift type and annotating that type with the @Suite attribute.

The @Suite attribute isn’t required for the testing library to recognize that a type contains test functions, but adding it allows customization of a test suite’s appearance in the IDE and at the command line. If a trait such as tags(_:) or disabled(_:sourceLocation:) is applied to a test suite, it’s automatically inherited by the tests contained in the suite.

In addition to containing test functions and any other members that a Swift type might contain, test suite types can also contain additional test suites nested within them. To add a nested test suite type, simply declare an additional type within the scope of the outer test suite type.

By default, tests contained within a suite run in parallel with each other. For more information about test parallelization, see Running tests serially or in parallel.

To customize a test suite’s name, supply a string literal as an argument to the @Suite attribute:

@Suite("Food truck tests") struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}

To further customize the appearance and behavior of a test function, use traits such as tags(_:).

If a type contains a test function declared as an instance method (that is, without either the static or class keyword), the testing library calls that test function at runtime by initializing an instance of the type, then calling the test function on that instance. If a test suite type contains multiple test functions declared as instance methods, each one is called on a distinct instance of the type. Therefore, the following test suite and test function:

@Suite struct FoodTruckTests {
  @Test func foodTruckExists() { ... }
}

Are equivalent to:

@Suite struct FoodTruckTests {
  func foodTruckExists() { ... }

  @Test static func staticFoodTruckExists() {
    let instance = FoodTruckTests()
    instance.foodTruckExists()
  }
}

When using a type as a test suite, it’s subject to some constraints that are not otherwise applied to Swift types.

If a type contains test functions declared as instance methods, it must be possible to initialize an instance of the type with a zero-argument initializer. The initializer may be any combination of:

  • implicit or explicit

  • synchronous or asynchronous

  • throwing or non-throwing

  • private, fileprivate, internal, package, or public

For example:

@Suite struct FoodTruckTests {
  var batteryLevel = 100

  @Test func foodTruckExists() { ... } // ✅ OK: The type has an implicit init().
}

@Suite struct CashRegisterTests {
  private init(cashOnHand: Decimal = 0.0) async throws { ... }

  @Test func calculateSalesTax() { ... } // ✅ OK: The type has a callable init().
}

struct MenuTests {
  var foods: [Food]
  var prices: [Food: Decimal]

  @Test static func specialOfTheDay() { ... } // ✅ OK: The function is static.
  @Test func orderAllFoods() { ... } // ❌ ERROR: The suite type requires init().
}

The compiler emits an error when presented with a test suite that doesn’t meet this requirement.

Although @available can be applied to a test function to limit its availability at runtime, a test suite type (and any types that contain it) must not be annotated with the @available attribute:

@Suite struct FoodTruckTests { ... } // ✅ OK: The type is always available.

@available(macOS 11.0, *) // ❌ ERROR: The suite type must always be available.
@Suite struct CashRegisterTests { ... }

@available(macOS 11.0, *) struct MenuItemTests { // ❌ ERROR: The suite type's
                                                 // containing type must always
                                                 // be available too.
  @Suite struct BurgerTests { ... }
}

The compiler emits an error when presented with a test suite that doesn’t meet this requirement.

Defining test functions

Define a test function to validate that code is working correctly.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Organizing test functions with suite types

Custom Test Argument Encoding

Skip Navigation

Protocol

CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol CustomTestArgumentEncodable : Sendable

Implementing parameterized tests

The testing library checks whether a test argument conforms to this protocol, or any of several other known protocols, when running selected test cases. When a test argument conforms to this protocol, that conformance takes highest priority, and the testing library will then call encodeTestArgument(to:) on the argument. A type that conforms to this protocol is not required to conform to either Encodable or Decodable.

See Implementing parameterized tests for a list of the other supported ways to allow running selected test cases.

func encodeTestArgument(to: some Encoder) throws

Encode this test argument.

Required

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

struct Case

A single test case from a parameterized Test.

Current page is CustomTestArgumentEncodable

Defining Test Functions

Skip Navigation

Article

Defining test functions

Define a test function to validate that code is working correctly.

Defining a test function for a Swift package or project is straightforward.

To import the testing library, add the following to the Swift source file that contains the test:

import Testing

To declare a test function, write a Swift function declaration that doesn’t take any arguments, then prefix its name with the @Test attribute:

@Test func foodTruckExists() {
  // Test logic goes here.
}

This test function can be present at file scope or within a type. A type containing test functions is automatically a test suite and can be optionally annotated with the @Suite attribute. For more information about suites, see Organizing test functions with suite types.

Note that, while this function is a valid test function, it doesn’t actually perform any action or test any code. To check for expected values and outcomes in test functions, add expectations to the test function.

To customize a test function’s name as presented in an IDE or at the command line, supply a string literal as an argument to the @Test attribute:

@Test("Food truck exists") func foodTruckExists() { ... }

To further customize the appearance and behavior of a test function, use traits such as tags(_:).

As with other Swift functions, test functions can be marked async and throws to annotate them as concurrent or throwing, respectively. If a test is only safe to run in the main actor’s execution context (that is, from the main thread of the process), it can be annotated @MainActor:

@Test @MainActor func foodTruckExists() async throws { ... }

If a test function can only run on newer versions of an operating system or of the Swift language, use the @available attribute when declaring it. Use the message argument of the @available attribute to specify a message to log if a test is unable to run due to limited availability:

@available(macOS 11.0, *)
@available(swift, introduced: 8.0, message: "Requires Swift 8.0 features to run")
@Test func foodTruckExists() { ... }

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Defining test functions

Interpreting Bug Identifiers

Skip Navigation

Article

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

The testing library supports two distinct ways to identify a bug:

  1. A URL linking to more information about the bug; and

  2. A unique identifier in the bug’s associated bug-tracking system.

A bug may have both an associated URL and an associated unique identifier. It must have at least one or the other in order for the testing library to be able to interpret it correctly.

To create an instance of Bug with a URL, use the bug(_:_:) trait. At compile time, the testing library will validate that the given string can be parsed as a URL according to RFC 3986.

To create an instance of Bug with a bug’s unique identifier, use the bug(_:id:_:) trait. The testing library does not require that a bug’s unique identifier match any particular format, but will interpret unique identifiers starting with "FB" as referring to bugs tracked with the Apple Feedback Assistant. For convenience, you can also directly pass an integer as a bug’s identifier using bug(_:id:_:).

Trait Function Inferred Bug-Tracking System
.bug(id: 12345) None
.bug(id: "12345") None
.bug("https://www.example.com?id=12345", id: "12345") None
.bug("https://github.com/swiftlang/swift/pull/12345") GitHub Issues for the Swift project
.bug("https://bugs.webkit.org/show_bug.cgi?id=12345") WebKit Bugzilla
.bug(id: "FB12345") Apple Feedback Assistant

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Interpreting bug identifiers

Limiting Test Execution Time

Skip Navigation

Article

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

Some tests may naturally run slowly: they may require significant system resources to complete, may rely on downloaded data from a server, or may otherwise be dependent on external factors.

If a test may hang indefinitely or may consume too many system resources to complete effectively, consider setting a time limit for it so that it’s marked as failing if it runs for an excessive amount of time. Use the timeLimit(_:) trait as an upper bound:

@Test(.timeLimit(.minutes(60))
func serve100CustomersInOneHour() async {
  for _ in 0 ..< 100 {
    let customer = await Customer.next()
    await customer.order()
    ...
  }
}

If the above test function takes longer than an hour (60 x 60 seconds) to execute, the task in which it’s running is cancelled and the test fails with an issue of kind Issue.Kind.timeLimitExceeded(timeLimitComponents:).

The testing library may adjust the specified time limit for performance reasons or to ensure tests have enough time to run. In particular, a granularity of (by default) one minute is applied to tests. The testing library can also be configured with a maximum time limit per test that overrides any applied time limit traits.

When a time limit is applied to a test suite, it’s recursively applied to all test functions and child test suites within that suite.

When a time limit is applied to a parameterized test function, it’s applied to each invocation separately so that if only some arguments cause failures, then successful arguments aren’t incorrectly marked as failing too.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is Limiting the running time of tests

Test Scoping Protocol

Skip Navigation

Protocol

TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Swift 6.1+Xcode 16.3+

protocol TestScoping : Sendable

Provide custom scope for tests by implementing the scopeProvider(for:testCase:) method, returning a type that conforms to this protocol. Create a custom scope to consolidate common set-up and tear-down logic for tests which have similar needs, which allows each test function to focus on the unique aspects of its test.

func provideScope(for: Test, testCase: Test.Case?, performing: () async throws -> Void) async throws

Provide custom execution scope for a function call which is related to the specified test or test case.

Required

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

Current page is TestScoping

Event Confirmation Type

Skip Navigation

Structure

Confirmation

A type that can be used to confirm that an event occurs zero or more times.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Confirmation

Testing asynchronous code

Migrating a test from XCTest

func callAsFunction(count: Int)

Confirm this confirmation.

func confirm(count: Int)

Confirm this confirmation.

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

Current page is Confirmation

Tag Type Overview

Skip Navigation

Structure

Tag

A type representing a tag that can be applied to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Tag

Adding tags to tests

To apply tags to a test, use the tags(_:) function.

struct List

A type representing one or more tags applied to a test.

API Reference\ CodingKeyRepresentable Implementations

API Reference\ Comparable Implementations

API Reference\ CustomStringConvertible Implementations

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Tag

SuiteTrait Protocol

Skip Navigation

Protocol

SuiteTrait

A protocol describing a trait that you can add to a test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol SuiteTrait : Trait

The testing library defines a number of traits that you can add to test suites. You can also define your own traits by creating types that conform to this protocol, or to the TestTrait protocol.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

Required Default implementation provided.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is SuiteTrait

Trait Protocol

Skip Navigation

Protocol

Trait

A protocol describing traits that can be added to a test function or to a test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol Trait : Sendable

The testing library defines a number of traits that can be added to test functions and to test suites. Define your own traits by creating types that conform to TestTrait or SuiteTrait:

TestTrait

Conform to this type in traits that you add to test functions.

SuiteTrait

Conform to this type in traits that you add to test suites.

You can add a trait that conforms to both TestTrait and SuiteTrait to test functions and test suites.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

static func tags(Tag...) -> Self

Construct a list of tags to apply to a test.

var comments: [Comment]

The user-provided comments for this trait.

Required Default implementation provided.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self.TestScopeProvider?

Get this trait’s scope provider for the specified test and optional test case.

Required Default implementations provided.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

Required Default implementation provided.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is Trait

Expectation Failed Error

Skip Navigation

Structure

ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ExpectationFailedError

The testing library throws instances of this type when the #require() macro records an issue.

var expectation: Expectation

The expectation that failed.

struct Expectation

A type describing an expectation that has been evaluated.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

Current page is ExpectationFailedError

Time Limit Trait

Skip Navigation

Structure

TimeLimitTrait

A type that defines a time limit to apply to a test.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

struct TimeLimitTrait

To add this trait to a test, use timeLimit(_:).

struct Duration

A type representing the duration of a time limit applied to a test.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var timeLimit: Duration

The maximum amount of time a test may run for before timing out.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

Current page is TimeLimitTrait

Swift Expectation Type

Skip Navigation

Structure

Expectation

A type describing an expectation that has been evaluated.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Expectation

var isPassing: Bool

Whether the expectation passed or failed.

var isRequired: Bool

Whether or not the expectation was required to pass.

var sourceLocation: SourceLocation

The source location where this expectation was evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

Current page is Expectation

Parameterized Testing in Swift

Skip Navigation

Article

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

Some tests need to be run over many different inputs. For instance, a test might need to validate all cases of an enumeration. The testing library lets developers specify one or more collections to iterate over during testing, with the elements of those collections being forwarded to a test function. An invocation of a test function with a particular set of argument values is called a test case.

By default, the test cases of a test function run in parallel with each other. For more information about test parallelization, see Running tests serially or in parallel.

It is very common to want to run a test n times over an array containing the values that should be tested. Consider the following test function:

enum Food {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available")
func foodsAvailable() async throws {
  for food: Food in [.burger, .iceCream, .burrito, .noodleBowl, .kebab] {
    let foodTruck = FoodTruck(selling: food)
    #expect(await foodTruck.cook(food))
  }
}

If this test function fails for one of the values in the array, it may be unclear which value failed. Instead, the test function can be parameterized over the various inputs:

enum Food {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available", arguments: [Food.burger, .iceCream, .burrito, .noodleBowl, .kebab])
func foodAvailable(_ food: Food) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food))
}

When passing a collection to the @Test attribute for parameterization, the testing library passes each element in the collection, one at a time, to the test function as its first (and only) argument. Then, if the test fails for one or more inputs, the corresponding diagnostics can clearly indicate which inputs to examine.

The previous example includes a hard-coded list of Food cases to test. If Food is an enumeration that conforms to CaseIterable, you can instead write:

enum Food: CaseIterable {
  case burger, iceCream, burrito, noodleBowl, kebab
}

@Test("All foods available", arguments: Food.allCases)
func foodAvailable(_ food: Food) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food))
}

This way, if a new case is added to the Food enumeration, it’s automatically tested by this function.

It is possible to parameterize a test function over a closed range of integers:

@Test("Can make large orders", arguments: 1 ... 100)
func makeLargeOrder(count: Int) async throws {
  let foodTruck = FoodTruck(selling: .burger)
  #expect(await foodTruck.cook(.burger, quantity: count))
}

It’s possible to test more than one collection. Consider the following test function:

@Test("Can make large orders", arguments: Food.allCases, 1 ... 100)
func makeLargeOrder(of food: Food, count: Int) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food, quantity: count))
}

Elements from the first collection are passed as the first argument to the test function, elements from the second collection are passed as the second argument, and so forth.

Assuming there are five cases in the Food enumeration, this test function will, when run, be invoked 500 times (5 x 100) with every possible combination of food and order size. These combinations are referred to as the collections’ Cartesian product.

To avoid the combinatoric semantics shown above, use zip():

@Test("Can make large orders", arguments: zip(Food.allCases, 1 ... 100))
func makeLargeOrder(of food: Food, count: Int) async throws {
  let foodTruck = FoodTruck(selling: food)
  #expect(await foodTruck.cook(food, quantity: count))
}

The zipped sequence will be “destructured” into two arguments automatically, then passed to the test function for evaluation.

This revised test function is invoked once for each tuple in the zipped sequence, for a total of five invocations instead of 500 invocations. In other words, this test function is passed the inputs (.burger, 1), (.iceCream, 2), …, (.kebab, 5) instead of (.burger, 1), (.burger, 2), (.burger, 3), …, (.kebab, 99), (.kebab, 100).

If a parameterized test meets certain requirements, the testing library allows people to run specific test cases it contains. This can be useful when a test has many cases but only some are failing since it enables re-running and debugging the failing cases in isolation.

To support running selected test cases, it must be possible to deterministically match the test case’s arguments. When someone attempts to run selected test cases of a parameterized test function, the testing library evaluates each argument of the tests’ cases for conformance to one of several known protocols, and if all arguments of a test case conform to one of those protocols, that test case can be run selectively. The following lists the known protocols, in precedence order (highest to lowest):

  1. CustomTestArgumentEncodable

  2. RawRepresentable, where RawValue conforms to Encodable

  3. Encodable

  4. Identifiable, where ID conforms to Encodable

If any argument of a test case doesn’t meet one of the above requirements, then the overall test case cannot be run selectively.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Implementing parameterized tests

Condition Trait

Skip Navigation

Structure

ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ConditionTrait

Migrating a test from XCTest

To add this trait to a test, use one of the following functions:

var comments: [Comment]

The user-provided comments for this trait.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var sourceLocation: SourceLocation

The source location where this trait is specified.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ConditionTrait

SourceLocation in Swift

Skip Navigation

Structure

SourceLocation

A type representing a location in source code.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct SourceLocation

init(fileID: String, filePath: String, line: Int, column: Int)

Initialize an instance of this type with the specified location details.

var column: Int

The column in the source file.

var fileID: String

The file ID of the source file.

var fileName: String

The name of the source file.

var line: Int

The line in the source file.

var moduleName: String

The name of the module containing the source file.

API Reference\ Comparable Implementations

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

Current page is SourceLocation

Bug Reporting Structure

Skip Navigation

Structure

Bug

A type that represents a bug report tracked by a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Bug

Interpreting bug identifiers

Adding comments to tests

To add this trait to a test, use one of the following functions:

var id: String?

A unique identifier in this bug’s associated bug-tracking system, if available.

var title: Comment?

The human-readable title of the bug, if specified by the test author.

var url: String?

A URL that links to more information about the bug, if available.

API Reference\ Decodable Implementations

API Reference\ Encodable Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Bug

Swift Test Traits

Skip Navigation

Collection

API Collection

Traits

Annotate test functions and suites, and customize their behavior.

Pass built-in traits to test functions or suite types to comment, categorize, classify, and modify the runtime behavior of test suites and test functions. Implement the TestTrait, and SuiteTrait protocols to create your own types that customize the behavior of your tests.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Running tests serially or in parallel

Control whether tests run serially or in parallel.

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol TestTrait

A protocol describing a trait that you can add to a test function.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Traits

Custom Test String

Skip Navigation

Protocol

CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol CustomTestStringConvertible

Values whose types conform to this protocol use it to describe themselves when they are present as part of the output of a test. For example, this protocol affects the display of values that are passed as arguments to test functions or that are elements of an expectation failure.

By default, the testing library converts values to strings using String(describing:). The resulting string may be inappropriate for some types and their values. If the type of the value is made to conform to CustomTestStringConvertible, then the value of its testDescription property will be used instead.

For example, consider the following type:

enum Food: CaseIterable {
  case paella, oden, ragu
}

If an array of cases from this enumeration is passed to a parameterized test function:

@Test(arguments: Food.allCases)
func isDelicious(_ food: Food) { ... }

Then the values in the array need to be presented in the test output, but the default description of a value may not be adequately descriptive:

◇ Passing argument food → .paella to isDelicious(_:)
◇ Passing argument food → .oden to isDelicious(_:)
◇ Passing argument food → .ragu to isDelicious(_:)

By adopting CustomTestStringConvertible, customized descriptions can be included:

extension Food: CustomTestStringConvertible {
  var testDescription: String {
    switch self {
    case .paella:
      "paella valenciana"
    case .oden:
      "おでん"
    case .ragu:
      "ragù alla bolognese"
    }
  }
}

The presentation of these values will then reflect the value of the testDescription property:

◇ Passing argument food → paella valenciana to isDelicious(_:)
◇ Passing argument food → おでん to isDelicious(_:)
◇ Passing argument food → ragù alla bolognese to isDelicious(_:)

var testDescription: String

A description of this instance to use when presenting it in a test’s output.

Required Default implementation provided.

struct Expectation

A type describing an expectation that has been evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

Current page is CustomTestStringConvertible

Swift Testing Issues

Skip Navigation

Structure

Issue

A type describing a failure or warning which occurred during a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Issue

Associating bugs with tests

Interpreting bug identifiers

var comments: [Comment]

Any comments provided by the developer and associated with this issue.

var error: (any Error)?

The error which was associated with this issue, if any.

var kind: Issue.Kind

The kind of issue this value represents.

var sourceLocation: SourceLocation?

The location in source where this issue occurred, if available.

static func record(any Error, Comment?, sourceLocation: SourceLocation) -> Issue

Record a new issue when a running test unexpectedly catches an error.

static func record(Comment?, sourceLocation: SourceLocation) -> Issue

Record an issue when a running test fails unexpectedly.

enum Kind

Kinds of issues which may be recorded.

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

Current page is Issue

Migrating from XCTest

Skip Navigation

Article

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

The testing library provides much of the same functionality of XCTest, but uses its own syntax to declare test functions and types. Here, you’ll learn how to convert XCTest-based content to use the testing library instead.

XCTest and the testing library are available from different modules. Instead of importing the XCTest module, import the Testing module:

// Before
import XCTest

// After
import Testing

A single source file can contain tests written with XCTest as well as other tests written with the testing library. Import both XCTest and Testing if a source file contains mixed test content.

XCTest groups related sets of test methods in test classes: classes that inherit from the XCTestCase class provided by the XCTest framework. The testing library doesn’t require that test functions be instance members of types. Instead, they can be free or global functions, or can be static or class members of a type.

If you want to group your test functions together, you can do so by placing them in a Swift type. The testing library refers to such a type as a suite. These types do not need to be classes, and they don’t inherit from XCTestCase.

To convert a subclass of XCTestCase to a suite, remove the XCTestCase conformance. It’s also generally recommended that a Swift structure or actor be used instead of a class because it allows the Swift compiler to better-enforce concurrency safety:

// Before
class FoodTruckTests: XCTestCase {
  ...
}

// After
struct FoodTruckTests {
  ...
}

For more information about suites and how to declare and customize them, see Organizing test functions with suite types.

In XCTest, code can be scheduled to run before and after a test using the setUp() and tearDown() family of functions. When writing tests using the testing library, implement init() and/or deinit instead:

// Before
class FoodTruckTests: XCTestCase {
  var batteryLevel: NSNumber!
  override func setUp() async throws {
    batteryLevel = 100
  }
  ...
}

// After
struct FoodTruckTests {
  var batteryLevel: NSNumber
  init() async throws {
    batteryLevel = 100
  }
  ...
}

The use of async and throws is optional. If teardown is needed, declare your test suite as a class or as an actor rather than as a structure and implement deinit:

// Before
class FoodTruckTests: XCTestCase {
  var batteryLevel: NSNumber!
  override func setUp() async throws {
    batteryLevel = 100
  }
  override func tearDown() {
    batteryLevel = 0 // drain the battery
  }
  ...
}

// After
final class FoodTruckTests {
  var batteryLevel: NSNumber
  init() async throws {
    batteryLevel = 100
  }
  deinit {
    batteryLevel = 0 // drain the battery
  }
  ...
}

The testing library represents individual tests as functions, similar to how they are represented in XCTest. However, the syntax for declaring a test function is different. In XCTest, a test method must be a member of a test class and its name must start with test. The testing library doesn’t require a test function to have any particular name. Instead, it identifies a test function by the presence of the @Test attribute:

// Before
class FoodTruckTests: XCTestCase {
  func testEngineWorks() { ... }
  ...
}

// After
struct FoodTruckTests {
  @Test func engineWorks() { ... }
  ...
}

As with XCTest, the testing library allows test functions to be marked async, throws, or async- throws, and to be isolated to a global actor (for example, by using the @MainActor attribute.)

For more information about test functions and how to declare and customize them, see Defining test functions.

XCTest uses a family of approximately 40 functions to assert test requirements. These functions are collectively referred to as XCTAssert(). The testing library has two replacements, expect(_:_:sourceLocation:) and require(_:_:sourceLocation:). They both behave similarly to XCTAssert() except that require(_:_:sourceLocation:) throws an error if its condition isn’t met:

// Before
func testEngineWorks() throws {
  let engine = FoodTruck.shared.engine
  XCTAssertNotNil(engine.parts.first)
  XCTAssertGreaterThan(engine.batteryLevel, 0)
  try engine.start()
  XCTAssertTrue(engine.isRunning)
}

// After
@Test func engineWorks() throws {
  let engine = FoodTruck.shared.engine
  try #require(engine.parts.first != nil)
  #expect(engine.batteryLevel > 0)
  try engine.start()
  #expect(engine.isRunning)
}

XCTest also has a function, XCTUnwrap(), that tests if an optional value is nil and throws an error if it is. When using the testing library, you can use require(_:_:sourceLocation:) with optional expressions to unwrap them:

// Before
func testEngineWorks() throws {
  let engine = FoodTruck.shared.engine
  let part = try XCTUnwrap(engine.parts.first)
  ...
}

// After
@Test func engineWorks() throws {
  let engine = FoodTruck.shared.engine
  let part = try #require(engine.parts.first)
  ...
}

XCTest has a function, XCTFail(), that causes a test to fail immediately and unconditionally. This function is useful when the syntax of the language prevents the use of an XCTAssert() function. To record an unconditional issue using the testing library, use the record(_:sourceLocation:) function:

// Before
func testEngineWorks() {
  let engine = FoodTruck.shared.engine
  guard case .electric = engine else {
    XCTFail("Engine is not electric")
    return
  }
  ...
}

// After
@Test func engineWorks() {
  let engine = FoodTruck.shared.engine
  guard case .electric = engine else {
    Issue.record("Engine is not electric")
    return
  }
  ...
}

The following table includes a list of the various XCTAssert() functions and their equivalents in the testing library:

XCTest Swift Testing
XCTAssert(x), XCTAssertTrue(x) #expect(x)
XCTAssertFalse(x) #expect(!x)
XCTAssertNil(x) #expect(x == nil)
XCTAssertNotNil(x) #expect(x != nil)
XCTAssertEqual(x, y) #expect(x == y)
XCTAssertNotEqual(x, y) #expect(x != y)
XCTAssertIdentical(x, y) #expect(x === y)
XCTAssertNotIdentical(x, y) #expect(x !== y)
XCTAssertGreaterThan(x, y) #expect(x > y)
XCTAssertGreaterThanOrEqual(x, y) #expect(x >= y)
XCTAssertLessThanOrEqual(x, y) #expect(x <= y)
XCTAssertLessThan(x, y) #expect(x < y)
XCTAssertThrowsError(try f()) #expect(throws: (any Error).self) { try f() }
XCTAssertThrowsError(try f()) { error in … } let error = #expect(throws: (any Error).self) { try f() }
XCTAssertNoThrow(try f()) #expect(throws: Never.self) { try f() }
try XCTUnwrap(x) try #require(x)
XCTFail("…") Issue.record("…")

The testing library doesn’t provide an equivalent of XCTAssertEqual(_:_:accuracy:_:file:line:). To compare two numeric values within a specified accuracy, use isApproximatelyEqual() from swift-numerics.

An instance of an XCTestCase subclass can set its continueAfterFailure property to false to cause a test to stop running after a failure occurs. XCTest stops an affected test by throwing an Objective-C exception at the time the failure occurs.

The behavior of an exception thrown through a Swift stack frame is undefined. If an exception is thrown through an async Swift function, it typically causes the process to terminate abnormally, preventing other tests from running.

The testing library doesn’t use exceptions to stop test functions. Instead, use the require(_:_:sourceLocation:) macro, which throws a Swift error on failure:

// Before
func testTruck() async {
  continueAfterFailure = false
  XCTAssertTrue(FoodTruck.shared.isLicensed)
  ...
}

// After
@Test func truck() throws {
  try #require(FoodTruck.shared.isLicensed)
  ...
}

When using either continueAfterFailure or require(_:_:sourceLocation:), other tests will continue to run after the failed test method or test function.

XCTest has a class, XCTestExpectation, that represents some asynchronous condition. You create an instance of this class (or a subclass like XCTKeyPathExpectation) using an initializer or a convenience method on XCTestCase. When the condition represented by an expectation occurs, the developer fulfills the expectation. Concurrently, the developer waits for the expectation to be fulfilled using an instance of XCTWaiter or using a convenience method on XCTestCase.

Wherever possible, prefer to use Swift concurrency to validate asynchronous conditions. For example, if it’s necessary to determine the result of an asynchronous Swift function, it can be awaited with await. For a function that takes a completion handler but which doesn’t use await, a Swift continuation can be used to convert the call into an async-compatible one.

Some tests, especially those that test asynchronously-delivered events, cannot be readily converted to use Swift concurrency. The testing library offers functionality called confirmations which can be used to implement these tests. Instances of Confirmation are created and used within the scope of the functions confirmation(_:expectedCount:isolation:sourceLocation:_:) and confirmation(_:expectedCount:isolation:sourceLocation:_:).

Confirmations function similarly to the expectations API of XCTest, however, they don’t block or suspend the caller while waiting for a condition to be fulfilled. Instead, the requirement is expected to be confirmed (the equivalent of fulfilling an expectation) before confirmation() returns, and records an issue otherwise:

// Before
func testTruckEvents() async {
  let soldFood = expectation(description: "…")
  FoodTruck.shared.eventHandler = { event in
    if case .soldFood = event {
      soldFood.fulfill()
    }
  }
  await Customer().buy(.soup)
  await fulfillment(of: [soldFood])
  ...
}

// After
@Test func truckEvents() async {
  await confirmation("…") { soldFood in
    FoodTruck.shared.eventHandler = { event in
      if case .soldFood = event {
        soldFood()
      }
    }
    await Customer().buy(.soup)
  }
  ...
}

By default, XCTestExpectation expects to be fulfilled exactly once, and will record an issue in the current test if it is not fulfilled or if it is fulfilled more than once. Confirmation behaves the same way and expects to be confirmed exactly once by default. You can configure the number of times an expectation should be fulfilled by setting its expectedFulfillmentCount property, and you can pass a value for the expectedCount argument of confirmation(_:expectedCount:isolation:sourceLocation:_:) for the same purpose.

XCTestExpectation has a property, assertForOverFulfill, which when set to false allows an expectation to be fulfilled more times than expected without causing a test failure. When using a confirmation, you can pass a range to confirmation(_:expectedCount:isolation:sourceLocation:_:) as its expected count to indicate that it must be confirmed at least some number of times:

// Before
func testRegularCustomerOrders() async {
  let soldFood = expectation(description: "…")
  soldFood.expectedFulfillmentCount = 10
  soldFood.assertForOverFulfill = false
  FoodTruck.shared.eventHandler = { event in
    if case .soldFood = event {
      soldFood.fulfill()
    }
  }
  for customer in regularCustomers() {
    await customer.buy(customer.regularOrder)
  }
  await fulfillment(of: [soldFood])
  ...
}

// After
@Test func regularCustomerOrders() async {
  await confirmation(
    "…",
    expectedCount: 10...
  ) { soldFood in
    FoodTruck.shared.eventHandler = { event in
      if case .soldFood = event {
        soldFood()
      }
    }
    for customer in regularCustomers() {
      await customer.buy(customer.regularOrder)
    }
  }
  ...
}

Any range expression with a lower bound (that is, whose type conforms to both RangeExpression<Int> and Sequence<Int>) can be used with confirmation(_:expectedCount:isolation:sourceLocation:_:). You must specify a lower bound for the number of confirmations because, without one, the testing library cannot tell if an issue should be recorded when there have been zero confirmations.

When using XCTest, the XCTSkip error type can be thrown to bypass the remainder of a test function. As well, the XCTSkipIf() and XCTSkipUnless() functions can be used to conditionalize the same action. The testing library allows developers to skip a test function or an entire test suite before it starts running using the ConditionTrait trait type. Annotate a test suite or test function with an instance of this trait type to control whether it runs:

// Before
class FoodTruckTests: XCTestCase {
  func testArepasAreTasty() throws {
    try XCTSkipIf(CashRegister.isEmpty)
    try XCTSkipUnless(FoodTruck.sells(.arepas))
    ...
  }
  ...
}

// After
@Suite(.disabled(if: CashRegister.isEmpty))
struct FoodTruckTests {
  @Test(.enabled(if: FoodTruck.sells(.arepas)))
  func arepasAreTasty() {
    ...
  }
  ...
}

A test may have a known issue that sometimes or always prevents it from passing. When written using XCTest, such tests can call XCTExpectFailure(_:options:failingBlock:) to tell XCTest and its infrastructure that the issue shouldn’t cause the test to fail. The testing library has an equivalent function with synchronous and asynchronous variants:

This function can be used to annotate a section of a test as having a known issue:

// Before
func testGrillWorks() async {
  XCTExpectFailure("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  }
  ...
}

If a test may fail intermittently, the call to XCTExpectFailure(_:options:failingBlock:) can be marked non-strict. When using the testing library, specify that the known issue is intermittent instead:

// Before
func testGrillWorks() async {
  XCTExpectFailure(
    "Grill may need fuel",
    options: .nonStrict()
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue(
    "Grill may need fuel",
    isIntermittent: true
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

Additional options can be specified when calling XCTExpectFailure():

  • isEnabled can be set to false to skip known-issue matching (for instance, if a particular issue only occurs under certain conditions)

  • issueMatcher can be set to a closure to allow marking only certain issues as known and to allow other issues to be recorded as test failures

The testing library includes overloads of withKnownIssue() that take additional arguments with similar behavior:

To conditionally enable known-issue matching or to match only certain kinds of issues:

// Before
func testGrillWorks() async {
  let options = XCTExpectedFailure.Options()
  options.isEnabled = FoodTruck.shared.hasGrill
  options.issueMatcher = { issue in
    issue.type == thrownError
  }
  XCTExpectFailure(
    "Grill is out of fuel",
    options: options
  ) {
    try FoodTruck.shared.grill.start()
  }
  ...
}

// After
@Test func grillWorks() async {
  withKnownIssue("Grill is out of fuel") {
    try FoodTruck.shared.grill.start()
  } when: {
    FoodTruck.shared.hasGrill
  } matching: { issue in
    issue.error != nil
  }
  ...
}

By default, the testing library runs all tests in a suite in parallel. The default behavior of XCTest is to run each test in a suite sequentially. If your tests use shared state such as global variables, you may see unexpected behavior including unreliable test outcomes when you run tests in parallel.

Annotate your test suite with serialized to run tests within that suite serially:

// Before
class RefrigeratorTests : XCTestCase {
  func testLightComesOn() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    XCTAssertEqual(FoodTruck.shared.refrigerator.lightState, .on)
  }

  func testLightGoesOut() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    try FoodTruck.shared.refrigerator.closeDoor()
    XCTAssertEqual(FoodTruck.shared.refrigerator.lightState, .off)
  }
}

// After
@Suite(.serialized)
class RefrigeratorTests {
  @Test func lightComesOn() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    #expect(FoodTruck.shared.refrigerator.lightState == .on)
  }

  @Test func lightGoesOut() throws {
    try FoodTruck.shared.refrigerator.openDoor()
    try FoodTruck.shared.refrigerator.closeDoor()
    #expect(FoodTruck.shared.refrigerator.lightState == .off)
  }
}

For more information, see Running tests serially or in parallel.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

API Reference\ Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

API Reference\ Known issues

Highlight known issues when running tests.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

macro Test(String?, any TestTrait...)

Declare a test.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Migrating a test from XCTest

TestTrait Protocol

Skip Navigation

Protocol

TestTrait

A protocol describing a trait that you can add to a test function.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

protocol TestTrait : Trait

The testing library defines a number of traits that you can add to test functions. You can also define your own traits by creating types that conform to this protocol, or to the SuiteTrait protocol.

protocol Trait

A protocol describing traits that can be added to a test function or to a test suite.

protocol SuiteTrait

A protocol describing a trait that you can add to a test suite.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

Current page is TestTrait

Parallelization Trait

Skip Navigation

Structure

ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ParallelizationTrait

When you add this trait to a parameterized test function, that test runs its cases serially instead of in parallel. This trait has no effect when you apply it to a non-parameterized test function.

When you add this trait to a test suite, that suite runs its contained test functions (including their cases, when parameterized) and sub-suites serially instead of in parallel. If the sub-suites have children, they also run serially.

This trait does not affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if you disable test parallelization globally (for example, by passing --no-parallel to the swift test command.)

To add this trait to a test, use serialized.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ParallelizationTrait

Test Execution Control

Skip Navigation

Article

Running tests serially or in parallel

Control whether tests run serially or in parallel.

By default, tests run in parallel with respect to each other. Parallelization is accomplished by the testing library using task groups, and tests generally all run in the same process. The number of tests that run concurrently is controlled by the Swift runtime.

Parallelization can be disabled on a per-function or per-suite basis using the serialized trait:

@Test(.serialized, arguments: Food.allCases) func prepare(food: Food) {
  // This function will be invoked serially, once per food, because it has the
  // .serialized trait.
}

@Suite(.serialized) struct FoodTruckTests {
  @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) {
    // This function will be invoked serially, once per condiment, because the
    // containing suite has the .serialized trait.
  }

  @Test func startEngine() async throws {
    // This function will not run while refill(condiment:) is running. One test
    // must end before the other will start.
  }
}

When added to a parameterized test function, this trait causes that test to run its cases serially instead of in parallel. When applied to a non-parameterized test function, this trait has no effect. When applied to a test suite, this trait causes that suite to run its contained test functions and sub-suites serially instead of in parallel.

This trait is recursively applied: if it is applied to a suite, any parameterized tests or test suites contained in that suite are also serialized (as are any tests contained in those suites, and so on.)

This trait doesn’t affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if test parallelization is globally disabled (by, for example, passing --no-parallel to the swift test command.)

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Current page is Running tests serially or in parallel

Enabling Tests

Skip Navigation

Article

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Often, a test is only applicable in specific circumstances. For instance, you might want to write a test that only runs on devices with particular hardware capabilities, or performs locale-dependent operations. The testing library allows you to add traits to your tests that cause runners to automatically skip them if conditions like these are not met.

If you need to disable a test unconditionally, use the disabled(_:sourceLocation:) function. Given the following test function:

@Test("Food truck sells burritos")
func sellsBurritos() async throws { ... }

Add the trait after the test’s display name:

@Test("Food truck sells burritos", .disabled())
func sellsBurritos() async throws { ... }

The test will now always be skipped.

It’s also possible to add a comment to the trait to present in the output from the runner when it skips the test:

@Test("Food truck sells burritos", .disabled("We only sell Thai cuisine"))
func sellsBurritos() async throws { ... }

Sometimes, it makes sense to enable a test only when a certain condition is met. Consider the following test function:

@Test("Ice cream is cold")
func isCold() async throws { ... }

If it’s currently winter, then presumably ice cream won’t be available for sale and this test will fail. It therefore makes sense to only enable it if it’s currently summer. You can conditionally enable a test with enabled(if:_:sourceLocation:):

@Test("Ice cream is cold", .enabled(if: Season.current == .summer))
func isCold() async throws { ... }

It’s also possible to conditionally disable a test and to combine multiple conditions:

@Test(
  "Ice cream is cold",
  .enabled(if: Season.current == .summer),
  .disabled("We ran out of sprinkles")
)
func isCold() async throws { ... }

If a test is disabled because of a problem for which there is a corresponding bug report, you can use one of these functions to show the relationship between the test and the bug report:

For example, the following test cannot run due to bug number "12345":

@Test(
  "Ice cream is cold",
  .enabled(if: Season.current == .summer),
  .disabled("We ran out of sprinkles"),
  .bug(id: "12345")
)
func isCold() async throws { ... }

If a test has multiple conditions applied to it, they must all pass for it to run. Otherwise, the test notes the first condition to fail as the reason the test is skipped.

If a condition is complex, consider factoring it out into a helper function to improve readability:

func allIngredientsAvailable(for food: Food) -> Bool { ... }

@Test(
  "Can make sundaes",
  .enabled(if: Season.current == .summer),
  .enabled(if: allIngredientsAvailable(for: .sundae))
)
func makeSundae() async throws { ... }

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is Enabling and disabling tests

Testing Expectations

Skip Navigation

Collection

API Collection

Expectations and confirmations

Check for expected values, outcomes, and asynchronous events in tests.

Use expect(_:_:sourceLocation:) and require(_:_:sourceLocation:) macros to validate expected outcomes. To validate that an error is thrown, or not thrown, the testing library provides several overloads of the macros that you can use. For more information, see Testing for errors in Swift code.

Use a Confirmation to confirm the occurrence of an asynchronous event that you can’t check directly using an expectation. For more information, see Testing asynchronous code.

To validate that your code produces an expected value, use expect(_:_:sourceLocation:). This macro captures the expression you pass, and provides detailed information when the code doesn’t satisfy the expectation.

@Test func calculatingOrderTotal() {
  let calculator = OrderCalculator()
  #expect(calculator.total(of: [3, 3]) == 7)
  // Prints "Expectation failed: (calculator.total(of: [3, 3]) → 6) == 7"
}

Your test keeps running after expect(_:_:sourceLocation:) fails. To stop the test when the code doesn’t satisfy a requirement, use require(_:_:sourceLocation:) instead:

@Test func returningCustomerRemembersUsualOrder() throws {
  let customer = try #require(Customer(id: 123))
  // The test runner doesn't reach this line if the customer is nil.
  #expect(customer.usualOrder.countOfItems == 2)
}

require(_:_:sourceLocation:) throws an instance of ExpectationFailedError when your code fails to satisfy the requirement.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Testing for errors in Swift code

Ensure that your code handles errors in the way you expect.

macro expect<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?

Check that an expression always throws an error of a given type.

macro expect<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?

Check that an expression always throws a specific error.

macro expect<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> (any Error)?

Check that an expression always throws an error matching some condition.

Deprecated

macro require<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E

Check that an expression always throws an error of a given type, and throw an error if it does not.

macro require<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E

macro require<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> any Error

Check that an expression always throws an error matching some condition, and throw an error if it does not.

Deprecated

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

struct Expectation

A type describing an expectation that has been evaluated.

struct ExpectationFailedError

A type describing an error thrown when an expectation fails during evaluation.

protocol CustomTestStringConvertible

A protocol describing types with a custom string representation when presented as part of a test’s output.

struct SourceLocation

A type representing a location in source code.

API Reference\ Known issues

Highlight known issues when running tests.

Current page is Expectations and confirmations

Known Issue Matcher

Skip Navigation

Type Alias

KnownIssueMatcher

A function that is used to match known issues.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

typealias KnownIssueMatcher = (Issue) -> Bool

issue

The issue to match.

Whether or not issue is known to occur.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void)

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void, when: () -> Bool, matching: KnownIssueMatcher) rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

Current page is KnownIssueMatcher

Associating Bugs with Tests

Skip Navigation

Article

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Tests allow developers to prove that the code they write is working as expected. If code isn’t working correctly, bug trackers are often used to track the work necessary to fix the underlying problem. It’s often useful to associate specific bugs with tests that reproduce them or verify they are fixed.

To associate a bug with a test, use one of these functions:

The first argument to these functions is a URL representing the bug in its bug-tracking system:

@Test("Food truck engine works", .bug("https://www.example.com/issues/12345"))
func engineWorks() async {
  var foodTruck = FoodTruck()
  await foodTruck.engine.start()
  #expect(foodTruck.engine.isRunning)
}

You can also specify the bug’s unique identifier in its bug-tracking system in addition to, or instead of, its URL:

@Test(
  "Food truck engine works",
  .bug(id: "12345"),
  .bug("https://www.example.com/issues/67890", id: 67890)
)
func engineWorks() async {
  var foodTruck = FoodTruck()
  await foodTruck.engine.start()
  #expect(foodTruck.engine.isRunning)
}

A bug’s URL is passed as a string and must be parseable according to RFC 3986. A bug’s unique identifier can be passed as an integer or as a string. For more information on the formats recognized by the testing library, see Interpreting bug identifiers.

A bug’s unique identifier or URL may be insufficient to uniquely and clearly identify a bug associated with a test. Bug trackers universally provide a “title” field for bugs that is not visible to the testing library. To add a bug’s title to a test, include it after the bug’s unique identifier or URL:

@Test(
  "Food truck has napkins",
  .bug(id: "12345", "Forgot to buy more napkins")
)
func hasNapkins() async {
  ...
}

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Associating bugs with tests

Test Comment Structure

Skip Navigation

Structure

Comment

A type that represents a comment related to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Comment

Use this type to provide context or background information about a test’s purpose, explain how a complex test operates, or include details which may be helpful when diagnosing issues recorded by a test.

To add a comment to a test or suite, add a code comment before its @Test or @Suite attribute. See Adding comments to tests for more details.

init(rawValue: String)

Creates a new instance with the specified raw value.

var rawValue: String

The single comment string that this comment contains.

typealias RawValue

The raw type that can be used to represent all values of the conforming type.

API Reference\ CustomStringConvertible Implementations

API Reference\ Equatable Implementations

API Reference\ ExpressibleByExtendedGraphemeClusterLiteral Implementations

API Reference\ ExpressibleByStringInterpolation Implementations

API Reference\ ExpressibleByStringLiteral Implementations

API Reference\ ExpressibleByUnicodeScalarLiteral Implementations

API Reference\ RawRepresentable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Comment

Swift Test Time Limit

Skip Navigation

Instance Property

timeLimit

The maximum amount of time this test’s cases may run for.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var timeLimit: Duration? { get }

Associate a time limit with tests by using timeLimit(_:).

If a test has more than one time limit associated with it, the value of this property is the shortest one. If a test has no time limits associated with it, the value of this property is nil.

Current page is timeLimit

Swift fileID Property

Skip Navigation

Instance Property

fileID

The file ID of the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var fileID: String { get set }

var moduleName: String

The name of the module containing the source file.

var fileName: String

The name of the source file.

Current page is fileID

Tag() Macro

Skip Navigation

Macro

Tag()

Declare a tag that can be applied to a test function or test suite.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(accessor) @attached(peer)
macro Tag()

Adding tags to tests

Use this tag with members of the Tag type declared in an extension to mark them as usable with tests. For more information on declaring tags, see Adding tags to tests.

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

static func bug(String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is Tag()

Swift Testing Error

Skip Navigation

Instance Property

error

The error which was associated with this issue, if any.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var error: (any Error)? { get }

The value of this property is non- nil when kind is Issue.Kind.errorCaught(_:).

Current page is error

Test Description Property

Skip Navigation

Instance Property

testDescription

A description of this instance to use when presenting it in a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var testDescription: String { get }

Required Default implementation provided.

Do not use this property directly. To get the test description of a value, use Swift/String/init(describingForTest:).

var testDescription: String

A description of this instance to use when presenting it in a test’s output.

Current page is testDescription

Source Location Trait

Skip Navigation

Instance Property

sourceLocation

The source location where this trait is specified.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation

Current page is sourceLocation

Swift Testing Name Property

Skip Navigation

Instance Property

name

The name of this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var name: String

The value of this property is equal to the name of the symbol to which the Test attribute is applied (that is, the name of the type or function.) To get the customized display name specified as part of the Test attribute, use the displayName property.

Current page is name

isRecursive Trait

Skip Navigation

Instance Property

isRecursive

Whether this instance should be applied recursively to child test suites and test functions.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isRecursive: Bool { get }

Required Default implementation provided.

If the value is true, then the testing library applies this trait recursively to child test suites and test functions. Otherwise, it only applies the trait to the test suite to which you added the trait.

By default, traits are not recursively applied to children.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

Current page is isRecursive

Swift fileName Property

Skip Navigation

Instance Property

fileName

The name of the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var fileName: String { get }

The name of the source file is derived from this instance’s fileID property. It consists of the substring of the file ID after the last forward-slash character ( "/".) For example, if the value of this instance’s fileID property is "FoodTruck/WheelTests.swift", the file name is "WheelTests.swift".

The structure of file IDs is described in the documentation for #fileID in the Swift standard library.

var fileID: String

The file ID of the source file.

var moduleName: String

The name of the module containing the source file.

Current page is fileName

Developer Comments Management

Skip Navigation

Instance Property

comments

Any comments provided by the developer and associated with this issue.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment]

If no comment was supplied when the issue occurred, the value of this property is the empty array.

Current page is comments

Source Location in Testing

Skip Navigation

Instance Property

sourceLocation

The location in source where this issue occurred, if available.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation? { get set }

Current page is sourceLocation

Test Comments

Skip Navigation

Instance Property

comments

The complete set of comments about this test from all of its traits.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment] { get }

Current page is comments

Test Duration Type

Skip Navigation

Structure

TimeLimitTrait.Duration

A type representing the duration of a time limit applied to a test.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

struct Duration

Use this type to specify a test timeout with TimeLimitTrait. TimeLimitTrait uses this type instead of Swift’s built-in Duration type because the testing library doesn’t support high-precision, arbitrarily short durations for test timeouts. The smallest unit of time you can specify in a Duration is minutes.

static func minutes(some BinaryInteger) -> TimeLimitTrait.Duration

Construct a time limit duration given a number of minutes.

Current page is TimeLimitTrait.Duration

Test Tags Overview

Skip Navigation

Instance Property

tags

The complete, unique set of tags associated with this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var tags: Set<Tag> { get }

Tags are associated with tests using the tags(_:) function.

Current page is tags

Customizing Display Names

Skip Navigation

Instance Property

displayName

The customized display name of this instance, if specified.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var displayName: String?

Current page is displayName

Serialized Trait

Skip Navigation

Type Property

serialized

A trait that serializes the test to which it is applied.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static var serialized: ParallelizationTrait { get }

Available when Self is ParallelizationTrait.

Migrating a test from XCTest

Running tests serially or in parallel

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

Running tests serially or in parallel

Control whether tests run serially or in parallel.

Current page is serialized

Swift Test Source Location

Skip Navigation

Instance Property

sourceLocation

The source location of this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var sourceLocation: SourceLocation

Current page is sourceLocation

Test Case Overview

Skip Navigation

Structure

Test.Case

A single test case from a parameterized Test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Case

A test case represents a test run with a particular combination of inputs. Tests that are not parameterized map to a single instance of Test.Case.

var isParameterized: Bool

Whether or not this test case is from a parameterized test.

static var current: Test.Case?

The test case that is running on the current task, if any.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

Current page is Test.Case

Tag List Overview

Skip Navigation

Structure

Tag.List

A type representing one or more tags applied to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct List

To add this trait to a test, use the tags(_:) function.

var tags: [Tag]

The list of tags contained in this instance.

API Reference\ CustomStringConvertible Implementations

API Reference\ Equatable Implementations

API Reference\ Hashable Implementations

API Reference\ SuiteTrait Implementations

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is Tag.List

Test Suite Indicator

Skip Navigation

Instance Property

isSuite

Whether or not this instance is a test suite containing other tests.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isSuite: Bool { get }

Instances of Test attached to types rather than functions are test suites. They do not contain any test logic of their own, but they may have traits added to them that also apply to their subtests.

A test suite can be declared using the Suite(_:_:) macro.

Current page is isSuite

Swift moduleName Property

Skip Navigation

Instance Property

moduleName

The name of the module containing the source file.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var moduleName: String { get }

The name of the module is derived from this instance’s fileID property. It consists of the substring of the file ID up to the first forward-slash character ( "/".) For example, if the value of this instance’s fileID property is "FoodTruck/WheelTests.swift", the module name is "FoodTruck".

The structure of file IDs is described in the documentation for the #fileID macro in the Swift standard library.

var fileID: String

The file ID of the source file.

var fileName: String

The name of the source file.

#fileID

Current page is moduleName

Swift Testing Comments

Skip Navigation

Instance Property

comments

The user-provided comments for this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var comments: [Comment] { get }

The default value of this property is an empty array.

Current page is comments

Associated Bugs in Testing

Skip Navigation

Instance Property

associatedBugs

The set of bugs associated with this test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var associatedBugs: [Bug] { get }

For information on how to associate a bug with a test, see the documentation for Bug.

Current page is associatedBugs

Expectation Requirement

Skip Navigation

Instance Property

isRequired

Whether or not the expectation was required to pass.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var isRequired: Bool

Current page is isRequired

Testing Asynchronous Code

Skip Navigation

Article

Testing asynchronous code

Validate whether your code causes expected events to happen.

The testing library integrates with Swift concurrency, meaning that in many situations you can test asynchronous code using standard Swift features. Mark your test function as async and, in the function body, await any asynchronous interactions:

@Test func priceLookupYieldsExpectedValue() async {
  let mozarellaPrice = await unitPrice(for: .mozarella)
  #expect(mozarellaPrice == 3)
}

In more complex situations you can use Confirmation to discover whether an expected event happens.

Call confirmation(_:expectedCount:isolation:sourceLocation:_:) in your asynchronous test function to create a Confirmation for the expected event. In the trailing closure parameter, call the code under test. Swift Testing passes a Confirmation as the parameter to the closure, which you call as a function in the event handler for the code under test when the event you’re testing for occurs:

@Test("OrderCalculator successfully calculates subtotal for no pizzas")
func subtotalForNoPizzas() async {
  let calculator = OrderCalculator()
  await confirmation() { confirmation in
    calculator.successHandler = { _ in confirmation() }
    _ = await calculator.subtotal(for: PizzaToppings(bases: []))
  }
}

If you expect the event to happen more than once, set the expectedCount parameter to the number of expected occurrences. The test passes if the number of occurrences during the test matches the expected count, and fails otherwise.

You can also pass a range to confirmation(_:expectedCount:isolation:sourceLocation:_:) if the exact number of times the event occurs may change over time or is random:

@Test("Customers bought sandwiches")
func boughtSandwiches() async {
  await confirmation(expectedCount: 0 ..< 1000) { boughtSandwich in
    var foodTruck = FoodTruck()
    foodTruck.orderHandler = { order in
      if order.contains(.sandwich) {
        boughtSandwich()
      }
    }
    await FoodTruck.operate()
  }
}

In this example, there may be zero customers or up to (but not including) 1,000 customers who order sandwiches. Any range expression which includes an explicit lower bound can be used:

Range Expression Usage
1... If an event must occur at least once
5... If an event must occur at least five times
1 ... 5 If an event must occur at least once, but not more than five times
0 ..< 100 If an event may or may not occur, but must not occur more than 99 times

To validate that a particular event doesn’t occur during a test, create a Confirmation with an expected count of 0:

@Test func orderCalculatorEncountersNoErrors() async {
  let calculator = OrderCalculator()
  await confirmation(expectedCount: 0) { confirmation in
    calculator.errorHandler = { _ in confirmation() }
    calculator.subtotal(for: PizzaToppings(bases: []))
  }
}

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

Current page is Testing asynchronous code

Swift Testing Tags

Skip Navigation

Instance Property

tags

The list of tags contained in this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var tags: [Tag]

This preserves the list of the tags exactly as they were originally specified, in their original order, including duplicate entries. To access the complete, unique set of tags applied to a Test, see tags.

Current page is tags

Current Test Case

Skip Navigation

Type Property

current

The test case that is running on the current task, if any.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static var current: Test.Case? { get }

If the current task is running a test, or is a subtask of another task that is running a test, the value of this property describes the test’s currently-running case. If no test is currently running, the value of this property is nil.

If the current task is detached from a task that started running a test, or if the current thread was created without using Swift concurrency (e.g. by using Thread.detachNewThread(_:) or DispatchQueue.async(execute:)), the value of this property may be nil.

Current page is current

Parallelization Trait

Skip Navigation

Structure

ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ParallelizationTrait

When you add this trait to a parameterized test function, that test runs its cases serially instead of in parallel. This trait has no effect when you apply it to a non-parameterized test function.

When you add this trait to a test suite, that suite runs its contained test functions (including their cases, when parameterized) and sub-suites serially instead of in parallel. If the sub-suites have children, they also run serially.

This trait does not affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if you disable test parallelization globally (for example, by passing --no-parallel to the swift test command.)

To add this trait to a test, use serialized.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ParallelizationTrait

Condition Trait Overview

Skip Navigation

Structure

ConditionTrait

A type that defines a condition which must be satisfied for the testing library to enable a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct ConditionTrait

Migrating a test from XCTest

To add this trait to a test, use one of the following functions:

var comments: [Comment]

The user-provided comments for this trait.

var isRecursive: Bool

Whether this instance should be applied recursively to child test suites and test functions.

var sourceLocation: SourceLocation

The source location where this trait is specified.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

typealias TestScopeProvider

The type of the test scope provider for this trait.

API Reference\ Trait Implementations

struct Bug

A type that represents a bug report tracked by a test.

struct Comment

A type that represents a comment related to a test.

struct ParallelizationTrait

A type that defines whether the testing library runs this test serially or in parallel.

struct Tag

A type representing a tag that can be applied to a test.

struct List

A type representing one or more tags applied to a test.

struct TimeLimitTrait

A type that defines a time limit to apply to a test.

Current page is ConditionTrait

TestScopeProvider Overview

Skip Navigation

Type Alias

Comment.TestScopeProvider

The type of the test scope provider for this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

typealias TestScopeProvider = Never

The default type is Never, which can’t be instantiated. The scopeProvider(for:testCase:)-cjmg method for any trait with Never as its test scope provider type must return nil, meaning that the trait doesn’t provide a custom scope for tests it’s applied to.

Current page is Comment.TestScopeProvider

Bug Identifier Overview

Skip Navigation

Instance Property

id

A unique identifier in this bug’s associated bug-tracking system, if available.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var id: String?

For more information on how the testing library interprets bug identifiers, see Interpreting bug identifiers.

Current page is id

TestScopeProvider Overview

Skip Navigation

Type Alias

TimeLimitTrait.TestScopeProvider

The type of the test scope provider for this trait.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

typealias TestScopeProvider = Never

The default type is Never, which can’t be instantiated. The scopeProvider(for:testCase:)-cjmg method for any trait with Never as its test scope provider type must return nil, meaning that the trait doesn’t provide a custom scope for tests it’s applied to.

Current page is TimeLimitTrait.TestScopeProvider

Test Duration Limit

Skip Navigation

Instance Property

timeLimit

The maximum amount of time a test may run for before timing out.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var timeLimit: Duration

Current page is timeLimit

Swift Issue Kind

Skip Navigation

Instance Property

kind

The kind of issue this value represents.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var kind: Issue.Kind

Current page is kind

Time Limit Trait

Skip Navigation

Type Method

timeLimit(_:)

Construct a time limit trait that causes a test to time out if it runs for too long.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

static func timeLimit(_ timeLimit: TimeLimitTrait.Duration) -> Self

Available when Self is TimeLimitTrait.

timeLimit

The maximum amount of time the test may run for.

An instance of TimeLimitTrait.

Limiting the running time of tests

Test timeouts do not support high-precision, arbitrarily short durations due to variability in testing environments. You express the duration in minutes, with a minimum duration of one minute.

When you associate this trait with a test, that test must complete within a time limit of, at most, timeLimit. If the test runs longer, the testing library records a Issue.Kind.timeLimitExceeded(timeLimitComponents:) issue, which it treats as a test failure.

The testing library can use a shorter time limit than that specified by timeLimit if you configure it to enforce a maximum per-test limit. When you configure a maximum per-test limit, the time limit of the test this trait is applied to is the shorter of timeLimit and the maximum per-test limit. For information on configuring maximum per-test limits, consult the documentation for the tool you use to run your tests.

If a test is parameterized, this time limit is applied to each of its test cases individually. If a test has more than one time limit associated with it, the testing library uses the shortest time limit.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

Current page is timeLimit(_:)

Swift Testing Comment

Skip Navigation

Instance Property

rawValue

The single comment string that this comment contains.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var rawValue: String

To get the complete set of comments applied to a test, see comments.

Current page is rawValue

isRecursive Property Overview

Skip Navigation

Instance Property

isRecursive

Whether this instance should be applied recursively to child test suites and test functions.

iOS 16.0+iPadOS 16.0+Mac Catalyst 16.0+macOS 13.0+tvOS 16.0+visionOSwatchOS 9.0+Swift 6.0+Xcode 16.0+

var isRecursive: Bool { get }

If the value is true, then the testing library applies this trait recursively to child test suites and test functions. Otherwise, it only applies the trait to the test suite to which you added the trait.

By default, traits are not recursively applied to children.

Current page is isRecursive

Test Preparation Method

Skip Navigation

Instance Method

prepare(for:)

Prepare to run the test that has this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func prepare(for test: Test) async throws

test

The test that has this trait.

The testing library calls this method after it discovers all tests and their traits, and before it begins to run any tests. Use this method to prepare necessary internal state, or to determine whether the test should run.

The default implementation of this method does nothing.

Current page is prepare(for:)

Test Preparation Method

Skip Navigation

Instance Method

prepare(for:)

Prepare to run the test that has this trait.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func prepare(for test: Test) async throws

Required Default implementation provided.

test

The test that has this trait.

The testing library calls this method after it discovers all tests and their traits, and before it begins to run any tests. Use this method to prepare necessary internal state, or to determine whether the test should run.

The default implementation of this method does nothing.

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self.TestScopeProvider?

Get this trait’s scope provider for the specified test and optional test case.

Required Default implementations provided.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

Current page is prepare(for:)

Swift Testing Tags

Skip Navigation

Type Method

tags(_:)

Construct a list of tags to apply to a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func tags(_ tags: Tag...) -> Self

Available when Self is Tag.List.

tags

The list of tags to apply to the test.

An instance of Tag.List containing the specified tags.

Organizing test functions with suite types

Defining test functions

Adding tags to tests

var comments: [Comment]

The user-provided comments for this trait.

Required Default implementation provided.

Current page is tags(_:)

Swift Testing ID

Skip Navigation

Instance Property

id

The stable identity of the entity associated with this instance.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var id: Test.ID { get }

Current page is id

Swift Test Description

Skip Navigation

Instance Property

testDescription

A description of this instance to use when presenting it in a test’s output.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

var testDescription: String { get }

Available when Self conforms to StringProtocol.

Do not use this property directly. To get the test description of a value, use Swift/String/init(describingForTest:).

Current page is testDescription

Bug Tracking Method

Skip Navigation

Type Method

bug(_:_:)

Constructs a bug to track with a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func bug(
    _ url: String,
    _ title: Comment? = nil
) -> Self

Available when Self is Bug.

url

A URL that refers to this bug in the associated bug-tracking system.

title

Optionally, the human-readable title of the bug.

An instance of Bug that represents the specified bug.

Associating bugs with tests

Enabling and disabling tests

Interpreting bug identifiers

Adding tags to tests

Use tags to provide semantic information for organization, filtering, and customizing appearances.

Adding comments to tests

Add comments to provide useful information about tests.

Associating bugs with tests

Associate bugs uncovered or verified by tests.

Interpreting bug identifiers

Examine how the testing library interprets bug identifiers provided by developers.

macro Tag()

Declare a tag that can be applied to a test function or test suite.

static func bug(String?, id: String, Comment?) -> Self

Constructs a bug to track with a test.

static func bug(String?, id: some Numeric, Comment?) -> Self

Constructs a bug to track with a test.

Current page is bug(_:_:)

Record Test Issues

Skip Navigation

Type Method

record(_:sourceLocation:)

Record an issue when a running test fails unexpectedly.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@discardableResult
static func record(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Issue

comment

A comment describing the expectation.

sourceLocation

The source location to which the issue should be attributed.

The issue that was recorded.

Migrating a test from XCTest

Use this function if, while running a test, an issue occurs that cannot be represented as an expectation (using the expect(_:_:sourceLocation:) or require(_:_:sourceLocation:) macros.)

Current page is record(_:sourceLocation:)

Scope Provider Method

Skip Navigation

Instance Method

scopeProvider(for:testCase:)

Get this trait’s scope provider for the specified test and optional test case.

Swift 6.1+Xcode 16.3+

func scopeProvider(
    for test: Test,
    testCase: Test.Case?
) -> Self.TestScopeProvider?

Required Default implementations provided.

test

The test for which a scope provider is being requested.

testCase

The test case for which a scope provider is being requested, if any. When test represents a suite, the value of this argument is nil.

A value conforming to TestScopeProvider which you use to provide custom scoping for test or testCase. Returns nil if the trait doesn’t provide any custom scope for the test or test case.

If this trait’s type conforms to TestScoping, the default value returned by this method depends on the values of test and testCase:

  • If test represents a suite, this trait must conform to SuiteTrait. If the value of this suite trait’s isRecursive property is true, then this method returns nil, and the suite trait provides its custom scope once for each test function the test suite contains. If the value of isRecursive is false, this method returns self, and the suite trait provides its custom scope once for the entire test suite.

  • If test represents a test function, this trait also conforms to TestTrait. If testCase is nil, this method returns nil; otherwise, it returns self. This means that by default, a trait which is applied to or inherited by a test function provides its custom scope once for each of that function’s cases.

A trait may override this method to further customize the default behaviors above. For example, if a trait needs to provide custom test scope both once per-suite and once per-test function in that suite, it implements the method to return a non- nil scope provider under those conditions.

A trait may also implement this method and return nil if it determines that it does not need to provide a custom scope for a particular test at runtime, even if the test has the trait applied. This can improve performance and make diagnostics clearer by avoiding an unnecessary call to provideScope(for:testCase:performing:).

If this trait’s type does not conform to TestScoping and its associated TestScopeProvider type is the default Never, then this method returns nil by default. This means that instances of this trait don’t provide a custom scope for tests to which they’re applied.

func scopeProvider(for: Test, testCase: Test.Case?) -> Never?

Get this trait’s scope provider for the specified test or test case.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self?

Get this trait’s scope provider for the specified test or test case.

func scopeProvider(for: Test, testCase: Test.Case?) -> Self?

Get this trait’s scope provider for the specified test and optional test case.

protocol TestScoping

A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.

associatedtype TestScopeProvider : TestScoping = Never

The type of the test scope provider for this trait.

Required

func prepare(for: Test) async throws

Prepare to run the test that has this trait.

Required Default implementation provided.

Current page is scopeProvider(for:testCase:)

Swift Testing Expectation

Skip Navigation

Macro

expect(_:_:sourceLocation:)

Check that an expectation has passed after a condition has been evaluated.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro expect(
    _ condition: Bool,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
)

condition

The condition to be evaluated.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

Testing for errors in Swift code

Migrating a test from XCTest

If condition evaluates to false, an Issue is recorded for the test that is running in the current task.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Current page is expect(_:_:sourceLocation:)

System Issue Kind

Skip Navigation

Case

Issue.Kind.system

An issue due to a failure in the underlying system, not due to a failure within the tests being run.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

case system

Current page is Issue.Kind.system

Disable Test Condition

Skip Navigation

Type Method

disabled(_:sourceLocation:)

Constructs a condition trait that disables a test unconditionally.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that always disables the test to which it is added.

Enabling and disabling tests

Organizing test functions with suite types

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(_:sourceLocation:)

Hashing Method

Skip Navigation

Instance Method

hash(into:)

Hashes the essential components of this value by feeding them into the given hasher.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func hash(into hasher: inout Hasher)

hasher

The hasher to use when combining the components of this instance.

Implement this method to conform to the Hashable protocol. The components used for hashing must be the same as the components compared in your type’s == operator implementation. Call hasher.combine(_:) with each of these components.

Current page is hash(into:)

Tag Comparison Operator

Skip Navigation

Operator

<(_:_:)

Returns a Boolean value indicating whether the value of the first argument is less than that of the second argument.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func < (lhs: Tag, rhs: Tag) -> Bool

lhs

A value to compare.

rhs

Another value to compare.

This function is the only requirement of the Comparable protocol. The remainder of the relational operator functions are implemented by the standard library for any type that conforms to Comparable.

Current page is <(_:_:)

Test Execution Control

Skip Navigation

Article

Running tests serially or in parallel

Control whether tests run serially or in parallel.

By default, tests run in parallel with respect to each other. Parallelization is accomplished by the testing library using task groups, and tests generally all run in the same process. The number of tests that run concurrently is controlled by the Swift runtime.

Parallelization can be disabled on a per-function or per-suite basis using the serialized trait:

@Test(.serialized, arguments: Food.allCases) func prepare(food: Food) {
  // This function will be invoked serially, once per food, because it has the
  // .serialized trait.
}

@Suite(.serialized) struct FoodTruckTests {
  @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) {
    // This function will be invoked serially, once per condiment, because the
    // containing suite has the .serialized trait.
  }

  @Test func startEngine() async throws {
    // This function will not run while refill(condiment:) is running. One test
    // must end before the other will start.
  }
}

When added to a parameterized test function, this trait causes that test to run its cases serially instead of in parallel. When applied to a non-parameterized test function, this trait has no effect. When applied to a test suite, this trait causes that suite to run its contained test functions and sub-suites serially instead of in parallel.

This trait is recursively applied: if it is applied to a suite, any parameterized tests or test suites contained in that suite are also serialized (as are any tests contained in those suites, and so on.)

This trait doesn’t affect the execution of a test relative to its peers or to unrelated tests. This trait has no effect if test parallelization is globally disabled (by, for example, passing --no-parallel to the swift test command.)

static var serialized: ParallelizationTrait

A trait that serializes the test to which it is applied.

Current page is Running tests serially or in parallel

Scope Provider Method

Skip Navigation

Instance Method

scopeProvider(for:testCase:)

Get this trait’s scope provider for the specified test or test case.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func scopeProvider(
    for test: Test,
    testCase: Test.Case?
) -> Never?

Available when TestScopeProvider is Never.

test

The test for which the testing library requests a scope provider.

testCase

The test case for which the testing library requests a scope provider, if any. When test represents a suite, the value of this argument is nil.

The testing library uses this implementation of scopeProvider(for:testCase:) when the trait type’s associated TestScopeProvider type is Never.

Current page is scopeProvider(for:testCase:)

Swift Test Issues

Skip Navigation

Structure

Issue

A type describing a failure or warning which occurred during a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Issue

Associating bugs with tests

Interpreting bug identifiers

var comments: [Comment]

Any comments provided by the developer and associated with this issue.

var error: (any Error)?

The error which was associated with this issue, if any.

var kind: Issue.Kind

The kind of issue this value represents.

var sourceLocation: SourceLocation?

The location in source where this issue occurred, if available.

static func record(any Error, Comment?, sourceLocation: SourceLocation) -> Issue

Record a new issue when a running test unexpectedly catches an error.

static func record(Comment?, sourceLocation: SourceLocation) -> Issue

Record an issue when a running test fails unexpectedly.

enum Kind

Kinds of issues which may be recorded.

API Reference\ CustomDebugStringConvertible Implementations

API Reference\ CustomStringConvertible Implementations

Current page is Issue

Confirmation Testing

Skip Navigation

Structure

Confirmation

A type that can be used to confirm that an event occurs zero or more times.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

struct Confirmation

Testing asynchronous code

Migrating a test from XCTest

func callAsFunction(count: Int)

Confirm this confirmation.

func confirm(count: Int)

Confirm this confirmation.

Testing asynchronous code

Validate whether your code causes expected events to happen.

func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

func confirmation<R>(Comment?, expectedCount: some RangeExpression<Int> & Sendable & Sequence<Int>, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R

Confirm that some event occurs during the invocation of a function.

Current page is Confirmation

Parameterized Test Macro

Skip Navigation

Macro

Test(_:_:arguments:)

Declare a test parameterized over two zipped collections of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C1, C2>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments zippedCollections: Zip2Sequence<C1, C2>
) where C1 : Collection, C1 : Sendable, C2 : Collection, C2 : Sendable, C1.Element : Sendable, C2.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

zippedCollections

Two zipped collections of values to pass to testFunction.

During testing, the associated test function is called once for each element in zippedCollections.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:)

Known Issue Function

Skip Navigation

  • Swift Testing
  • withKnownIssue(_:isIntermittent:sourceLocation:_:)

Function

withKnownIssue(_:isIntermittent:sourceLocation:_:)

Invoke a function that has a known issue that is expected to occur during its execution.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func withKnownIssue(
    _ comment: Comment? = nil,
    isIntermittent: Bool = false,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: () throws -> Void
)

comment

An optional comment describing the known issue.

isIntermittent

Whether or not the known issue occurs intermittently. If this argument is true and the known issue does not occur, no secondary issue is recorded.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

Migrating a test from XCTest

Use this function when a test is known to raise one or more issues that should not cause the test to fail. For example:

@Test func example() {
  withKnownIssue {
    try flakyCall()
  }
}

Because all errors thrown by body are caught as known issues, this function is not throwing. If only some errors or issues are known to occur while others should continue to cause test failures, use withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:) instead.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void, when: () -> Bool, matching: KnownIssueMatcher) rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

typealias KnownIssueMatcher

A function that is used to match known issues.

Current page is withKnownIssue(_:isIntermittent:sourceLocation:_:)

Event Confirmation Function

Skip Navigation

Function

confirmation(_:expectedCount:sourceLocation:_:)

Confirm that some event occurs during the invocation of a function.

Swift 6.0+Xcode 16.0+

func confirmation<R>(
    _ comment: Comment? = nil,
    expectedCount: Int = 1,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: (Confirmation) async throws -> R
) async rethrows -> R

comment

An optional comment to apply to any issues generated by this function.

expectedCount

The number of times the expected event should occur when body is invoked. The default value of this argument is 1, indicating that the event should occur exactly once. Pass 0 if the event should never occur when body is invoked.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

Whatever is returned by body.

Migrating a test from XCTest

Testing asynchronous code

Use confirmations to check that an event occurs while a test is running in complex scenarios where #expect() and #require() are insufficient. For example, a confirmation may be useful when an expected event occurs:

  • In a context that cannot be awaited by the calling function such as an event handler or delegate callback;

  • More than once, or never; or

  • As a callback that is invoked as part of a larger operation.

To use a confirmation, pass a closure containing the work to be performed. The testing library will then pass an instance of Confirmation to the closure. Every time the event in question occurs, the closure should call the confirmation:

let n = 10
await confirmation("Baked buns", expectedCount: n) { bunBaked in
  foodTruck.eventHandler = { event in
    if event == .baked(.cinnamonBun) {
      bunBaked()
    }
  }
  await foodTruck.bake(.cinnamonBun, count: n)
}

When the closure returns, the testing library checks if the confirmation’s preconditions have been met, and records an issue if they have not.

Testing asynchronous code

Validate whether your code causes expected events to happen.

struct Confirmation

A type that can be used to confirm that an event occurs zero or more times.

Current page is confirmation(_:expectedCount:sourceLocation:_:)

Disable Test Trait

Skip Navigation

Type Method

disabled(_:sourceLocation:_:)

Constructs a condition trait that disables a test if its value is true.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ condition: @escaping () async throws -> Bool
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns false, the trait allows the test to run. Otherwise, the testing library skips the test.

An instance of ConditionTrait that evaluates the specified closure.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(_:sourceLocation:_:)

Test Disabling Trait

Skip Navigation

Type Method

disabled(if:_:sourceLocation:)

Constructs a condition trait that disables a test if its value is true.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func disabled(
    if condition: @autoclosure @escaping () throws -> Bool,
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns false, the trait allows the test to run. Otherwise, the testing library skips the test.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that evaluates the closure you provide.

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if it returns false.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is disabled(if:_:sourceLocation:)

Condition Trait Management

Skip Navigation

Type Method

enabled(if:_:sourceLocation:)

Constructs a condition trait that disables a test if it returns false.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func enabled(
    if condition: @autoclosure @escaping () throws -> Bool,
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> Self

Available when Self is ConditionTrait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns true, the trait allows the test to run. Otherwise, the testing library skips the test.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

An instance of ConditionTrait that evaluates the closure you provide.

Enabling and disabling tests

Enabling and disabling tests

Conditionally enable or disable individual tests before they run.

Limiting the running time of tests

Set limits on how long a test can run for until it fails.

static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if it returns false.

static func disabled(Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test unconditionally.

static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self

Constructs a condition trait that disables a test if its value is true.

static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self

Constructs a condition trait that disables a test if its value is true.

static func timeLimit(TimeLimitTrait.Duration) -> Self

Construct a time limit trait that causes a test to time out if it runs for too long.

Current page is enabled(if:_:sourceLocation:)

Swift Testing Macro

Skip Navigation

Macro

require(_:_:sourceLocation:)

Unwrap an optional value or, if it is nil, fail and throw an error.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro require<T>(
    _ optionalValue: T?,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
) -> T

optionalValue

The optional value to be unwrapped.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

The unwrapped value of optionalValue.

Migrating a test from XCTest

If optionalValue is nil, an Issue is recorded for the test that is running in the current task and an instance of ExpectationFailedError is thrown.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

Current page is require(_:_:sourceLocation:)

Parameterized Test Declaration

Skip Navigation

Macro

Test(_:_:arguments:)

Declare a test parameterized over a collection of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments collection: C
) where C : Collection, C : Sendable, C.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

collection

A collection of values to pass to the associated test function.

During testing, the associated test function is called once for each element in collection.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2)

Declare a test parameterized over two collections of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:)

Swift Testing Macro

Skip Navigation

Macro

require(_:_:sourceLocation:)

Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@freestanding(expression)
macro require(
    _ condition: Bool,
    _ comment: @autoclosure () -> Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation
)

condition

The condition to be evaluated.

comment

A comment describing the expectation.

sourceLocation

The source location to which recorded expectations and issues should be attributed.

Migrating a test from XCTest

Testing for errors in Swift code

If condition evaluates to false, an Issue is recorded for the test that is running in the current task and an instance of ExpectationFailedError is thrown.

macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)

Check that an expectation has passed after a condition has been evaluated.

macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T

Unwrap an optional value or, if it is nil, fail and throw an error.

Current page is require(_:_:sourceLocation:)

Condition Trait Testing

Skip Navigation

Type Method

enabled(_:sourceLocation:_:)

Constructs a condition trait that disables a test if it returns false.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

static func enabled(
    _ comment: Comment? = nil,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ condition: @escaping () async throws -> Bool
) -> Self

Available when Self is ConditionTrait.

comment

An optional comment that describes this trait.

sourceLocation

The source location of the trait.

condition

A closure that contains the trait’s custom condition logic. If this closure returns true, the trait allows the test to run. Otherwise, the testing library skips the test.

An instance of ConditionTrait that evaluates the closure you provide.

Current page is enabled(_:sourceLocation:_:)

Known Issue Invocation

Skip Navigation

  • Swift Testing
  • withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Function

withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Invoke a function that has a known issue that is expected to occur during its execution.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

func withKnownIssue(
    _ comment: Comment? = nil,
    isIntermittent: Bool = false,
    sourceLocation: SourceLocation = #_sourceLocation,
    _ body: () throws -> Void,
    when precondition: () -> Bool = { true },
    matching issueMatcher: @escaping KnownIssueMatcher = { _ in true }
) rethrows

comment

An optional comment describing the known issue.

isIntermittent

Whether or not the known issue occurs intermittently. If this argument is true and the known issue does not occur, no secondary issue is recorded.

sourceLocation

The source location to which any recorded issues should be attributed.

body

The function to invoke.

precondition

A function that determines if issues are known to occur during the execution of body. If this function returns true, encountered issues that are matched by issueMatcher are considered to be known issues; if this function returns false, issueMatcher is not called and they are treated as unknown.

issueMatcher

A function to invoke when an issue occurs that is used to determine if the issue is known to occur. By default, all issues match.

Migrating a test from XCTest

Use this function when a test is known to raise one or more issues that should not cause the test to fail, or if a precondition affects whether issues are known to occur. For example:

@Test func example() throws {
  try withKnownIssue {
    try flakyCall()
  } when: {
    callsAreFlakyOnThisPlatform()
  } matching: { issue in
    issue.error is FileNotFoundError
  }
}

It is not necessary to specify both precondition and issueMatcher if only one is relevant. If all errors and issues should be considered known issues, use withKnownIssue(_:isIntermittent:sourceLocation:_:) instead.

func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void)

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async

Invoke a function that has a known issue that is expected to occur during its execution.

func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows

Invoke a function that has a known issue that is expected to occur during its execution.

typealias KnownIssueMatcher

A function that is used to match known issues.

Current page is withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)

Parameterized Testing in Swift

Skip Navigation

Macro

Test(_:_:arguments:_:)

Declare a test parameterized over two collections of values.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test<C1, C2>(
    _ displayName: String? = nil,
    _ traits: any TestTrait...,
    arguments collection1: C1,
    _ collection2: C2
) where C1 : Collection, C1 : Sendable, C2 : Collection, C2 : Sendable, C1.Element : Sendable, C2.Element : Sendable

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

collection1

A collection of values to pass to testFunction.

collection2

A second collection of values to pass to testFunction.

During testing, the associated test function is called once for each pair of elements in collection1 and collection2.

Defining test functions

Define a test function to validate that code is working correctly.

Implementing parameterized tests

Specify different input parameters to generate multiple test cases from a test function.

macro Test<C>(String?, any TestTrait..., arguments: C)

Declare a test parameterized over a collection of values.

macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)

Declare a test parameterized over two zipped collections of values.

protocol CustomTestArgumentEncodable

A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.

struct Case

A single test case from a parameterized Test.

Current page is Test(_:_:arguments:_:)

Test Declaration Macro

Skip Navigation

Macro

Test(_:_:)

Declare a test.

iOSiPadOSMac CatalystmacOStvOSvisionOSwatchOSSwift 6.0+Xcode 16.0+

@attached(peer)
macro Test(
    _ displayName: String? = nil,
    _ traits: any TestTrait...
)

displayName

The customized display name of this test. If the value of this argument is nil, the display name of the test is derived from the associated function’s name.

traits

Zero or more traits to apply to this test.

Defining test functions

Define a test function to validate that code is working correctly.

Defining test functions

Define a test function to validate that code is working correctly.

Organizing test functions with suite types

Organize tests into test suites.

Migrating a test from XCTest

Migrate an existing test method or test class written using XCTest.

struct Test

A type representing a test or suite.

macro Suite(String?, any SuiteTrait...)

Declare a test suite.

Current page is Test(_:_:)

)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment