Skip to content
Development
Skill

/swift-testing

Writes and migrates Swift Testing framework tests with @Test, @Suite, #expect, #require, confirmation, traits, withKnownIssue, Attachment.record, processExitsWith exit tests and capture lists, Test.cancel, Issue.record warnings/manual failures, XCTest-to-Swift Testing migration,

From plugin
swift-ios-skills
98186 skills1 MCP
Install
$ npx -y skills add dpearson2699/swift-ios-skills --skill swift-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/swift-testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Writes and migrates Swift Testing framework tests with @Test, @Suite, #expect, #require, confirmation, traits, withKnownIssue, Attachment.record, processExitsWith exit tests and capture lists, Test.cancel, Issue.record warnings/manual failures, XCTest-to-Swift Testing migration,

SKILL.md

swift-testing.SKILL.md
name: swift-testing
description: "Writes and migrates Swift Testing framework tests with @Test, @Suite, #expect, #require, confirmation, traits, withKnownIssue, Attachment.record, processExitsWith exit tests and capture lists, Test.cancel, Issue.record warnings/manual failures, XCTest-to-Swift Testing migration, Xcode 27 interoperability modes, XCUITest UI-test boundaries, performance/snapshot boundaries, mocking, async patterns, and test organization. Use when writing tests, converting XCTest assertions such as XCTUnwrap or XCTFail, reviewing advanced Swift Testing API availability, or deciding when to keep XCTest/XCUITest."

Swift Testing

Swift Testing is the modern testing framework for Swift (Xcode 16+, Swift 6+). Prefer it for new unit tests. Keep XCTest where migration is still in progress, and use XCTest for UI automation, performance APIs, Objective-C exception tests, and common snapshot-test tooling.

Contents

  • [Basic Tests](#basic-tests)
  • [`@Test Traits`](#test-traits)
  • [#expect and #require](#expect-and-require)
  • [`@Suite and Test Organization`](#suite-and-test-organization)
  • [Execution Model](#execution-model)
  • [XCTest Migration Boundaries](#xctest-migration-boundaries)
  • [Known Issues](#known-issues)
  • [Additional Patterns](#additional-patterns)
  • [Common Mistakes](#common-mistakes)
  • [Test Attachments](#test-attachments)
  • [Exit Testing](#exit-testing)
  • [Version-Gated APIs](#version-gated-apis)
  • [Review Checklist](#review-checklist)
  • [References](#references)

---

Basic Tests

import Testing

@Test("User can update their display name")
func updateDisplayName() {
    var user = User(name: "Alice")
    user.name = "Bob"
    #expect(user.name == "Bob")
}

`@Test` Traits

@Test("Validates email format")                                    // display name
@Test(.tags(.validation, .email))                                  // tags
@Test(.disabled("Server migration in progress"))                   // disabled
@Test(.enabled(if: ProcessInfo.processInfo.environment["CI"] != nil)) // conditional
@Test(.bug("https://github.com/org/repo/issues/42"))               // bug reference
@Test(.timeLimit(.minutes(1)))                                     // time limit
@Test("Timeout handling", .tags(.networking), .timeLimit(.seconds(30))) // combined

#expect and #require

// #expect records failure but continues execution
#expect(result == 42)
#expect(name.isEmpty == false)
#expect(items.count > 0, "Items should not be empty")

// #expect with error type checking
#expect(throws: ValidationError.self) {
    try validate(email: "not-an-email")
}

// #expect with specific error value
#expect {
    try validate(email: "")
} throws: { error in
    guard let err = error as? ValidationError else { return false }
    return err == .empty
}

// #require records failure AND stops test (like XCTUnwrap)
let user = try #require(await fetchUser(id: 1))
#expect(user.name == "Alice")

// #require for optionals -- unwraps or fails
let first = try #require(items.first)
#expect(first.isValid)

**Rule: Use `#require` when subsequent assertions depend on the value. Use `#expect` for independent checks.**

`@Suite` and Test Organization

See [references/testing-patterns.md](references/testing-patterns.md) for suite organization, confirmation patterns, known-issue handling, and execution-model details.

Execution Model

Swift Testing runs tests in parallel by default. Do not assume test order, shared suite instances, or exclusive access to mutable state unless you explicitly design for it.

@Suite(.serialized)
struct KeychainTests {
    @Test func storesToken() throws { /* ... */ }
    @Test func deletesToken() throws { /* ... */ }
}

Use `.serialized` when a test or suite must run one-at-a-time because it touches shared external state. It does not make unrelated tests outside that scope run serially.

**Rules:**

  • Each test must set up its own state.
  • Shared mutable globals are a bug unless protected or intentionally serialized.
  • `@Suite(.serialized)` is for exclusive execution, not for expressing logical ordering between tests.
  • If tests depend on sequence, combine them into one test or move the sequence into shared helper code.

XCTest Migration Boundaries

Swift Testing unit tests do not inherit from `XCTestCase`. Declare `@Test` on free functions or methods on suite types such as `struct`, `class`, or `actor`; use `static` or `class` methods when instance fixtures are unnecessary.

XCTest and Swift Testing can coexist during migration. Migrate one file or suite at a time, compare discovery/pass/fail/skip counts, and keep UI automation, performance benchmarks, and common snapshot flows on XCTest/XCUITest or snapshot tooling. Separate files or targets when that makes runner expectations clearer.

For Xcode 27-era mixed helpers, check the configured interoperability mode rather than claiming cross-framework APIs are forbidden. Older test plans inherit `limited`; new projects use `complete`; `strict` and `none` are also available. Prefer `complete` or `strict` during migration and use `SWIFT_TESTING_XCTEST_INTEROP_MODE` for SwiftPM when needed. See [references/testing-advanced.md](references/testing-advanced.md) for the mode matrix and toolchain gates.

Do not mechanically replace every XCTest assertion with `#expect`; preserve required unwraps and unconditional failures with these migration defaults:

  • `XCTAssert*` -> `#expect(...)`
  • `XCTUnwrap` or any value required by later checks -> `try #require(...)`
  • `XCTFail("...")` or manual unconditional issues -> `Issue.record("...")`
  • UI tests, performance benchmarks, and common snapshot-test flows stay on XCTest/XCUITest or snapshot tooling.
  • Put `@available` on individual `@Test` functions, not on suite types or their containing types.

See [references/testing-patterns.md](references/testing-patterns.md) for migration examples and [references/testing-advanced.md](refere

Read more
Ships withswift-ios-skills

86 agent skills optimized for iOS 26+ development with Swift 6.3 and modern Apple frameworks.

Get the whole plugin
Stats
981
Stars
50
Forks
Active
Maintenance
Python
Language
9d ago
Last commit
5mo ago
Created

Repo: dpearson2699/swift-ios-skills

Other skills on swift-ios-skills.