
Swift Testing
- 352 installs
- 297 repo stars
- Updated August 4, 2026
- vabole/apple-skills
swift-testing is a Claude Code skill that writes and organizes Swift Testing suites with #expect, parameterized cases, and tags for developers who need iOS logic validation before App Store submission.
About
swift-testing is a skill from vabole/apple-skills that helps developers write and organize Swift Testing suites for iOS projects. The skill covers #expect assertions, parameterized test cases, and tag-based suite organization so application logic is validated before App Store submission and regression cycles. Developers reach for swift-testing when adopting Apple’s Swift Testing framework instead of legacy XCTest patterns or when structuring new test files for native iOS codebases. It targets mobile engineers who need clear, maintainable unit and integration tests aligned with Swift Testing conventions.
- Uses #expect and #require for expressive assertions
- Supports parameterized and tagged test organization
- Tests async code with Swift concurrency-aware patterns
- Integrates with Xcode test plans and CI pipelines
- Covers mocks, fixtures, and regression-focused suites
Swift Testing by the numbers
- 352 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #668 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vabole/apple-skills --skill swift-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 352 |
|---|---|
| repo stars | ★ 297 |
| Last updated | August 4, 2026 |
| Repository | vabole/apple-skills ↗ |
How do you write Swift Testing suites for iOS apps?
Write and organize Swift Testing suites with #expect, parameterized cases, and tags to validate iOS logic before App Store submission and regression cycles.
Who is it for?
iOS developers adopting Swift Testing who need structured #expect suites before App Store releases.
Skip if: Android or cross-platform teams or projects still standardized on XCTest without migrating to Swift Testing.
When should I use this skill?
A developer is adding, organizing, or migrating iOS tests to Swift Testing with #expect, parameters, or tags.
What you get
Swift Testing test files with #expect assertions, parameterized cases, and tag-organized suites
- Swift Testing suite files
- Parameterized test cases
Files
Swift Testing Reference
Apple's modern testing framework (import Testing) for iOS 26+.
Downloaded Reference Files
| File | Content |
|---|---|
| testing-overview.md | Full Testing framework index |
| defining-tests.md | Defining test functions with @Test |
| organizing-tests.md | Organizing tests with @Suite |
| expectations.md | #expect, #require, confirmations |
| parameterized-testing.md | Parameterized test patterns |
| traits.md | Test traits (tags, conditions, time limits) |
| migrating-from-xctest.md | Migration guide from XCTest |
Fetching More Docs
1. Search this skill's local .md files first. 2. If the topic is not here, check the other installed Apple skills you have available by their names, descriptions, or SKILL.md frontmatter, then grep their local files. This is faster and uses less context than fetching new docs from the internet. 3. If no installed skill has the page, use the relevant documentation path from testing-overview.md with the sosumi.ai Markdown mirror. For example, /documentation/testing/test maps to https://sosumi.ai/documentation/testing/test.
Navigation: Testing
Article
Defining test functions
Define a test function to validate that code is working correctly.
Overview
Defining a test function for a Swift package or project is straightforward.
Import the testing library
To import the testing library, add the following to the Swift source file that contains the test:
import TestingNote: Only import the testing library into a test target or library meant for test targets. Importing the testing library into a target intended for distribution such as an application, app library, or executable target isn’t supported or recommended. Test functions aren’t stripped from binaries when building for release, so logic and fixtures of a test may be visible to anyone who inspects a build product that contains a test function.
Declare a test function
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 and confirmations to the test function.
Customize a test’s name
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(_:)).
Write concurrent or throwing tests
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 { ... }Limit the availability of a test
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() { ... }Essentials
- 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.
- Test(_:_:)) Declare a test.
- Test A type representing a test or suite.
- Suite(_:_:)) Declare a test suite.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
API Collection
Expectations and confirmations
Check for expected values, outcomes, and asynchronous events in tests.
Overview
Use expect(_:_:sourceLocation:)) and require(_:_:sourceLocation:)-5l63q) 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.
Validate your code’s result
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:)-5l63q) 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:)-5l63q) throws an instance of ExpectationFailedError when your code fails to satisfy the requirement.
Checking expectations
- expect(_:_:sourceLocation:)) Check that an expectation has passed after a condition has been evaluated.
- require(_:_:sourceLocation:)-5l63q) Check that an expectation has passed after a condition has been evaluated and throw an error if it failed.
- require(_:_:sourceLocation:)-6w9oo) Unwrap an optional value or, if it is
nil, fail and throw an error.
Checking that errors are thrown
- Testing for errors in Swift code Ensure that your code handles errors in the way you expect.
- expect(throws:_:sourceLocation:performing:)-1hfms) Check that an expression always throws an error of a given type.
- expect(throws:_:sourceLocation:performing:)-7du1h) Check that an expression always throws a specific error.
- expect(_:sourceLocation:performing:throws:)) Check that an expression always throws an error matching some condition.
- require(throws:_:sourceLocation:performing:)-7n34r) Check that an expression always throws an error of a given type, and throw an error if it does not.
- require(throws:_:sourceLocation:performing:)-4djuw)
- require(_:sourceLocation:performing:throws:)) Check that an expression always throws an error matching some condition, and throw an error if it does not.
Checking how processes exit
- Exit testing Use exit tests to test functionality that might cause a test process to exit.
- expect(processExitsWith:observing:_:sourceLocation:performing:)) Check that an expression causes the process to terminate in a given fashion.
- require(processExitsWith:observing:_:sourceLocation:performing:)) Check that an expression causes the process to terminate in a given fashion and throw an error if it did not.
- ExitStatus An enumeration describing possible status a process will report on exit.
- ExitTest A type describing an exit test.
Confirming that asynchronous events occur
- Testing asynchronous code Validate whether your code causes expected events to happen.
- confirmation(_:expectedCount:isolation:sourceLocation:_:)-5mqz2) Confirm that some event occurs during the invocation of a function.
- confirmation(_:expectedCount:isolation:sourceLocation:_:)-l3il) Confirm that some event occurs during the invocation of a function.
- Confirmation A type that can be used to confirm that an event occurs zero or more times.
Retrieving information about checked expectations
- Expectation A type describing an expectation that has been evaluated.
- ExpectationFailedError A type describing an error thrown when an expectation fails during evaluation.
- CustomTestStringConvertible A protocol describing types with a custom string representation when presented as part of a test’s output.
Representing source locations
- SourceLocation A type representing a location in source code.
Behavior validation
- Known issues Mark issues as known when running tests.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
Article
Migrating a test from XCTest
Migrate an existing test method or test class written using XCTest.
Overview
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.
Import the testing library
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 TestingA 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.
Convert test classes
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.
Convert setup and teardown functions
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
}
...
}Convert test methods
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.)
Note: XCTest runs synchronous test methods on the main actor by default, while the testing library runs all test functions on an arbitrary task. If a test function must run on the main thread, isolate it to the main actor with @MainActor, or run the thread-sensitive code inside a call to MainActor.run(resultType:body:)).For more information about test functions and how to declare and customize them, see Defining test functions.
Check for expected values and outcomes
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:)-5l63q). They both behave similarly to XCTAssert() except that require(_:_:sourceLocation:)-5l63q) 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)
}Check for optional values
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:)-6w9oo) 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)
...
}Record issues
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(_:severity: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.
Continue or halt after test failures
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.
Note: continueAfterFailure isn’t fully supported when using the swift-corelibs-xctest library on non-Apple platforms.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:)-5l63q) 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:)-5l63q), other tests will continue to run after the failed test method or test function.
Validate asynchronous behaviors
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:_:)-5mqz2) and confirmation(_:expectedCount:isolation:sourceLocation:_:)-l3il).
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:_:)-5mqz2) 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:_:)-l3il) 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:_:)-l3il). 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.
Control whether a test runs
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() {
...
}
...
}If a test is running and you determine it cannot complete and should end early without failing, use cancel(_:sourceLocation:)) instead of XCTSkip to cancel the task associated with the current test:
// Before
func testCashRegister() throws {
let cashRegister = CashRegister()
let drawer = cashRegister.open()
if drawer.isEmpty {
throw XCTSkip("Cash register is empty")
}
...
}// After
@Test func cashRegister() throws {
let cashRegister = CashRegister()
let drawer = cashRegister.open()
if drawer.isEmpty {
try Test.cancel("Cash register is empty")
}
...
}Annotate known issues
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:
- withKnownIssue(_:isIntermittent:sourceLocation:_:))
- withKnownIssue(_:isIntermittent:isolation:sourceLocation:_:))
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()
}
...
}Note: The XCTest function XCTExpectFailure(_:options:), which doesn’t take a closure and which affects the remainder of the test, doesn’t have a direct equivalent in the testing library. To mark an entire test as having a known issue, wrap its body in a call to withKnownIssue().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
falseto 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:
- withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:))
- withKnownIssue(_:isIntermittent:isolation:sourceLocation:_:when:matching:))
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
}
...
}Run tests sequentially
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.
Attach values
In XCTest, you can create an instance of XCTAttachment representing arbitrary data, files, property lists, encodable objects, images, and other types of information that would be useful to have available if a test fails. Swift Testing has an Attachment type that serves much the same purpose.
To attach a value from a test to the output of a test run, that value must conform to the Attachable protocol. The testing library provides default conformances for various standard library and Foundation types.
If you want to attach a value of another type, and that type already conforms to Encodable or to NSSecureCoding, the testing library automatically provides a default implementation when you import Foundation:
// Before
import Foundation
class Tortilla: NSSecureCoding { /* ... */ }
func testTortillaIntegrity() async {
let tortilla = Tortilla(diameter: .large)
...
let attachment = XCTAttachment(
archivableObject: tortilla
)
self.add(attachment)
}// After
import Foundation
struct Tortilla: Codable, Attachable { /* ... */ }
@Test func tortillaIntegrity() async {
let tortilla = Tortilla(diameter: .large)
...
Attachment.record(tortilla)
}If you have a type that does not (or cannot) conform to Encodable or NSSecureCoding, or if you want fine-grained control over how it is serialized when attaching it to a test, you can provide your own implementation of withUnsafeBytes(for:_:)).
Related Documentation
- 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.
- Expectations and confirmations Check for expected values, outcomes, and asynchronous events in tests.
- Known issues Mark issues as known when running tests.
Essentials
- 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.
- Test(_:_:)) Declare a test.
- Test A type representing a test or suite.
- Suite(_:_:)) Declare a test suite.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
Article
Organizing test functions with suite types
Organize tests into test suites.
Overview
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
@Suiteattribute.
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.
Customize a suite’s name
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(_:)).
Test functions in test suite types
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()
}
}Constraints on test suite types
When using a type as a test suite, it’s subject to some constraints that are not otherwise applied to Swift types.
An initializer may be required
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, orpublic
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.
Test suite types must always be available
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.
Essentials
- 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.
- Test(_:_:)) Declare a test.
- Test A type representing a test or suite.
- Suite(_:_:)) Declare a test suite.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
Article
Implementing parameterized tests
Specify different input parameters to generate multiple test cases from a test function.
Overview
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.
Parameterize over an array of values
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.
Parameterize over the cases of an enumeration
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.
Parameterize over a range of integers
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))
}Note: Very large ranges such as 0 ..< .max may take an excessive amount of time to test, or may never complete due to resource constraints.Pass the same arguments to multiple test functions
If you want to pass the same collection of arguments to two or more parameterized test functions, you can extract the arguments to a separate function or property and pass it to each @Test attribute. For example:
extension Food {
static var bestSelling: [Food] {
get async throws { /* ... */ }
}
}
@Test(arguments: try await Food.bestSelling)
func `Order entree`(food: Food) {
let foodTruck = FoodTruck()
#expect(foodTruck.order(food))
}
@Test(arguments: try await Food.bestSelling)
func `Package leftovers`(food: Food) throws {
let foodTruck = FoodTruck()
let container = try #require(foodTruck.container(fitting: food))
try container.add(food)
}Tip: You can prefix expressions passed toarguments:withtryorawait. The testing library evaluates them lazily only if it determines that the associated test will run.
Test with more than one collection
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, and elements from the second collection are passed as the second argument.
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).
Run selected test cases
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.
Test parameterization
- Test(_:_:arguments:)-8kn7a) Declare a test parameterized over a collection of values.
- Test(_:_:arguments:_:)) Declare a test parameterized over two collections of values.
- Test(_:_:arguments:)-3rzok) Declare a test parameterized over two zipped collections of values.
- CustomTestArgumentEncodable A protocol for customizing how arguments passed to parameterized tests are encoded, which is used to match against when running specific arguments.
- Test.Case A single test case from a parameterized Test.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
Essentials
- Defining test functions
- Organizing test functions with suite types
- Migrating a test from XCTest
- macro Test(String?, any TestTrait...))
- Test
Structures
Instance Properties
Type Properties
Instance Properties
- [var associatedBugs: [Bug]](/documentation/testing/test/associatedbugs)
- [var comments: [Comment]](/documentation/testing/test/comments)
- var displayName: String?
- var isParameterized: Bool
- var isSuite: Bool
- var name: String
- var sourceLocation: SourceLocation
- var tags: Set<Tag>
- var timeLimit: Duration?
- [var traits: [any Trait]](/documentation/testing/test/traits)
Type Properties
Type Methods
Test parameterization
- Implementing parameterized tests
- macro Test<C>(String?, any TestTrait..., arguments: C)-8kn7a)
- macro Test<C1, C2>(String?, any TestTrait..., arguments: C1, C2))
- macro Test<C1, C2>(String?, any TestTrait..., arguments: Zip2Sequence<C1, C2>)-3rzok)
- CustomTestArgumentEncodable
Instance Methods
Instance Properties
Type Properties
Behavior validation
Checking expectations
- macro expect(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation))
- macro require(Bool, @autoclosure () -> Comment?, sourceLocation: SourceLocation)-5l63q)
- macro require<T>(T?, @autoclosure () -> Comment?, sourceLocation: SourceLocation) -> T-6w9oo)
Checking that errors are thrown
- Testing for errors in Swift code
- macro expect<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?-1hfms)
- macro expect<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E?-7du1h)
- macro expect<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> (any Error)?)
- macro require<E, R>(throws: E.Type, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E-7n34r)
- macro require<E, R>(throws: E, @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R) -> E-4djuw)
- macro require<R>(@autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> R, throws: (any Error) async throws -> Bool) -> any Error)
Checking how processes exit
- Exit testing
- [macro expect(processExitsWith: ExitTest.Condition, observing: [any PartialKeyPath<ExitTest.Result> & Sendable], @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> Void) -> ExitTest.Result?](/documentation/testing/expect(processexitswith:observing:_:sourcelocation:performing:))
- [macro require(processExitsWith: ExitTest.Condition, observing: [any PartialKeyPath<ExitTest.Result> & Sendable], @autoclosure () -> Comment?, sourceLocation: SourceLocation, performing: () async throws -> Void) -> ExitTest.Result](/documentation/testing/require(processexitswith:observing:_:sourcelocation:performing:))
- ExitStatus
Enumeration Cases
Structures
Successful exit conditions
Failing exit conditions
- static var failure: ExitTest.Condition
- static func exitCode(CInt) -> ExitTest.Condition)
- static func signal(CInt) -> ExitTest.Condition)
Initializers
Instance Properties
- var exitStatus: ExitStatus
- [var standardErrorContent: [UInt8]](/documentation/testing/exittest/result/standarderrorcontent)
- [var standardOutputContent: [UInt8]](/documentation/testing/exittest/result/standardoutputcontent)
Type Properties
Confirming that asynchronous events occur
- Testing asynchronous code
- func confirmation<R>(Comment?, expectedCount: Int, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, (Confirmation) async throws -> sending R) async rethrows -> R-5mqz2)
- 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-l3il)
- Confirmation
Instance Methods
Retrieving information about checked expectations
Instance Properties
Instance Properties
Instance Properties
CustomTestStringConvertible Implementations
Representing source locations
Initializers
Instance Properties
- var column: Int
- var fileID: String
- var fileName: String
- var filePath: String
- var line: Int
- var moduleName: String
Recording known issues in tests
- func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void))
- func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void) async)
- func withKnownIssue(Comment?, isIntermittent: Bool, sourceLocation: SourceLocation, () throws -> Void, when: () -> Bool, matching: KnownIssueMatcher) rethrows)
- func withKnownIssue(Comment?, isIntermittent: Bool, isolation: isolated (any Actor)?, sourceLocation: SourceLocation, () async throws -> Void, when: () async -> Bool, matching: KnownIssueMatcher) async rethrows)
- KnownIssueMatcher
Describing a failure or warning
Instance Properties
- [var comments: [Comment]](/documentation/testing/issue/comments)
- var error: (any Error)?
- var isFailure: Bool
- var kind: Issue.Kind
- var severity: Issue.Severity
- var sourceLocation: SourceLocation?
Type Methods
- static func record(any Error, Comment?, sourceLocation: SourceLocation) -> Issue)
- static func record(Comment?, severity: Issue.Severity, sourceLocation: SourceLocation) -> Issue)
- static func record(Comment?, sourceLocation: SourceLocation) -> Issue)
Enumerations
Enumeration Cases
- case apiMisused
- case confirmationMiscounted(actual: Int, expected: any RangeExpression & Sendable))
- case errorCaught(any Error))
- case expectationFailed(Expectation))
- case knownIssueNotRecorded
- case system
- case timeLimitExceeded(timeLimitComponents: (seconds: Int64, attoseconds: Int64)))
- case unconditional
- case valueAttachmentFailed(any Error))
Enumeration Cases
Test customization
Customizing runtime behaviors
- Enabling and disabling tests
- Limiting the running time of tests
- static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self)
- static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self)
- static func disabled(Comment?, sourceLocation: SourceLocation) -> Self)
- static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self)
- static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self)
- static func timeLimit(TimeLimitTrait.Duration) -> Self)
Running tests serially or in parallel
Annotating tests
- Adding tags to tests
- Adding comments to tests
- Associating bugs with tests
- Interpreting bug identifiers
- macro Tag())
- static func bug(String, Comment?) -> Self)
- static func bug(String?, id: String, Comment?) -> Self-10yf5)
- static func bug(String?, id: some Numeric, Comment?) -> Self-3vtpl)
Handling issues
- static func compactMapIssues((Issue) -> Issue?) -> Self)
- static func filterIssues((Issue) -> Bool) -> Self)
Creating custom traits
Enabling and disabling tests
- static func enabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self)
- static func enabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self)
- static func disabled(Comment?, sourceLocation: SourceLocation) -> Self)
- static func disabled(if: @autoclosure () throws -> Bool, Comment?, sourceLocation: SourceLocation) -> Self)
- static func disabled(Comment?, sourceLocation: SourceLocation, () async throws -> Bool) -> Self)
Controlling how tests are run
Categorizing tests and adding information
- static func tags(Tag...) -> Self)
- [var comments: [Comment]](/documentation/testing/trait/comments)
Trait Implementations
- [var comments: [Comment]](/documentation/testing/trait/comments-5i8gy)
Associating bugs
- static func bug(String, Comment?) -> Self)
- static func bug(String?, id: String, Comment?) -> Self-10yf5)
- static func bug(String?, id: some Numeric, Comment?) -> Self-3vtpl)
Running code before and after a test or suite
Instance Methods
- func provideScope(for: Test, testCase: Test.Case?, performing: () async throws -> Void) async throws)
Trait Implementations
- func scopeProvider(for: Test, testCase: Test.Case?) -> Self?-1z8kh)
- func scopeProvider(for: Test, testCase: Test.Case?) -> Never?-9fxg4)
- func scopeProvider(for: Test, testCase: Test.Case?) -> Self?-inmj)
Trait Implementations
Type Methods
- static func compactMapIssues((Issue) -> Issue?) -> Self)
- static func filterIssues((Issue) -> Bool) -> Self)
Instance Properties
SuiteTrait Implementations
Instance Methods
- func provideScope(for: Test, testCase: Test.Case?, performing: () async throws -> Void) async throws)
Supporting types
Instance Properties
Instance Properties
Instance Properties
Instance Methods
Instance Methods
Structures
Instance Properties
- [var tags: [Tag]](/documentation/testing/tag/list/tags)
Instance Properties
- [var tags: [Tag]](/documentation/testing/tag/list/tags)
Structures
Type Methods
Instance Properties
Data collection
Attaching values to tests
Initializers
- init<T>(T, named: String?, as: AttachableImageFormat?, sourceLocation: SourceLocation))
- init(consuming AttachableValue, named: String?, sourceLocation: SourceLocation))
- init(contentsOf: URL, named: String?, sourceLocation: SourceLocation) async throws)
Instance Properties
- var attachableValue: AttachableValue
- var attachableValue: AttachableValue.Wrapped
- var imageFormat: AttachableImageFormat?
- var preferredName: String
Instance Methods
Type Methods
- static func record<T>(T, named: String?, as: AttachableImageFormat?, sourceLocation: SourceLocation))
- static func record(consuming AttachableValue, named: String?, sourceLocation: SourceLocation))
- static func record(consuming Attachment<AttachableValue>, sourceLocation: SourceLocation))
Default Implementations
Instance Properties
Instance Properties
Attachable Implementations
- var estimatedAttachmentByteCount: Int?
- var estimatedAttachmentByteCount: Int?
- var estimatedAttachmentByteCount: Int?
Instance Methods
Attachable Implementations
- func preferredName(for: borrowing Attachment<Self>, basedOn: String) -> String-9bptj)
- func preferredName(for: borrowing Attachment<Self>, basedOn: String) -> String-aal5)
Attachable Implementations
- func withUnsafeBytes<R>(for: borrowing Attachment<Self>, (UnsafeRawBufferPointer) throws -> R) throws -> R-4m3s9)
- func withUnsafeBytes<R>(for: borrowing Attachment<Self>, (UnsafeRawBufferPointer) throws -> R) throws -> R-8ied9)
Associated Types
Instance Properties
Attaching images to tests
Instance Methods
- func withUnsafeBytes<R>(as: AttachableImageFormat, (UnsafeRawBufferPointer) throws -> R) throws -> R)
Initializers
- init(contentType: UTType, encodingQuality: Float))
- init?(pathExtension: String, encodingQuality: Float))
Instance Properties
Type Properties
Type Methods
Default Implementations
Instance Properties
Instance Properties
- init<T>(T, named: String?, as: AttachableImageFormat?, sourceLocation: SourceLocation))
- static func record<T>(T, named: String?, as: AttachableImageFormat?, sourceLocation: SourceLocation))
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Testing
API Collection
Traits
Annotate test functions and suites, and customize their behavior.
Overview
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.
Customizing runtime behaviors
- 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.
- enabled(if:_:sourceLocation:)) Constructs a condition trait that disables a test if it returns
false. - enabled(_:sourceLocation:_:)) Constructs a condition trait that disables a test if it returns
false. - disabled(_:sourceLocation:)) Constructs a condition trait that disables a test unconditionally.
- disabled(if:_:sourceLocation:)) Constructs a condition trait that disables a test if its value is true.
- disabled(_:sourceLocation:_:)) Constructs a condition trait that disables a test if its value is true.
- timeLimit(_:)) Construct a time limit trait that causes a test to time out if it runs for too long.
Running tests serially or in parallel
- Running tests serially or in parallel Control whether tests run serially or in parallel.
- serialized A trait that serializes the test to which it is applied.
Annotating 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.
- Tag()) Declare a tag that can be applied to a test function or test suite.
- bug(_:_:)) Constructs a bug to track with a test.
- bug(_:id:_:)-10yf5) Constructs a bug to track with a test.
- bug(_:id:_:)-3vtpl) Constructs a bug to track with a test.
Handling issues
- compactMapIssues(_:)) Constructs an trait that transforms issues recorded by a test.
- filterIssues(_:)) Constructs a trait that filters issues recorded by a test.
Creating custom traits
- Trait A protocol describing traits that can be added to a test function or to a test suite.
- TestTrait A protocol describing a trait that you can add to a test function.
- SuiteTrait A protocol describing a trait that you can add to a test suite.
- TestScoping A protocol that tells the test runner to run custom code before or after it runs a test suite or test function.
Supporting types
- Bug A type that represents a bug report tracked by a test.
- Comment A type that represents a comment related to a test.
- ConditionTrait A type that defines a condition which must be satisfied for the testing library to enable a test.
- IssueHandlingTrait A type that allows transforming or filtering the issues recorded by a test.
- ParallelizationTrait A type that defines whether the testing library runs this test serially or in parallel.
- Tag A type representing a tag that can be applied to a test.
- Tag.List A type representing one or more tags applied to a test.
- TimeLimitTrait A type that defines a time limit to apply to a test.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Related skills
FAQ
Which Swift Testing features does swift-testing cover?
swift-testing helps developers write Swift Testing suites using #expect assertions, parameterized test cases, and tags. The skill organizes iOS test files for validation before App Store submission and regression runs.
When should iOS developers use swift-testing?
iOS developers should use swift-testing when adopting Apple’s Swift Testing framework for native app logic. The skill fits pre-release QA cycles that need structured suites instead of ad hoc XCTest-only patterns.