
Swift Testing
- 197 installs
- 222 repo stars
- Updated January 18, 2026
- johnrogers/claude-swift-engineering
Author and run Swift Testing suites with expressive tests, traits, parameterized cases, and CI-friendly discovery for iOS and Swift packages.
About
Swift-testing skill explains Apple’s Swift Testing framework: declare tests with #expect, group behavior with traits and tags, parameterize edge cases, test async and actor code safely, and integrate with Xcode and CI so mobile and package codebases gain reliable pre-release regression gates.
- Swift Testing macros
- Traits and tagging
- Parameterized test cases
- Async and actor testing
- CI discovery and reporting
Swift Testing by the numbers
- 197 all-time installs (skills.sh)
- +5 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #811 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/johnrogers/claude-swift-engineering --skill swift-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 197 |
|---|---|
| repo stars | ★ 222 |
| Last updated | January 18, 2026 |
| Repository | johnrogers/claude-swift-engineering ↗ |
What it does
Author and run Swift Testing suites with expressive tests, traits, parameterized cases, and CI-friendly discovery for iOS and Swift packages.
Files
Swift Testing Framework
Modern testing with Swift Testing framework. No XCTest.
Overview
Swift Testing replaces XCTest with a modern macro-based approach that's more concise, has better async support, and runs tests in parallel by default. The core principle: if you learned XCTest, unlearn it—Swift Testing works differently.
References
Core Concepts
Assertions
| Macro | Use Case |
|---|---|
#expect(expression) | Soft check — continues on failure. Use for most assertions. |
#require(expression) | Hard check — stops test on failure. Use for preconditions only. |
Optional Unwrapping
let user = try #require(await fetchUser(id: "123"))
#expect(user.id == "123")Test Structure
import Testing
@testable import YourModule
@Suite
struct FeatureTests {
let sut: FeatureType
init() throws {
sut = FeatureType()
}
@Test("Description of behavior")
func testBehavior() {
#expect(sut.someProperty == expected)
}
}Assertion Conversions
| XCTest | Swift Testing |
|---|---|
XCTAssert(expr) | #expect(expr) |
XCTAssertEqual(a, b) | #expect(a == b) |
XCTAssertNil(a) | #expect(a == nil) |
XCTAssertNotNil(a) | #expect(a != nil) |
try XCTUnwrap(a) | try #require(a) |
XCTAssertThrowsError | #expect(throws: ErrorType.self) { } |
XCTAssertNoThrow | #expect(throws: Never.self) { } |
Error Testing
#expect(throws: (any Error).self) { try riskyOperation() }
#expect(throws: NetworkError.self) { try fetch() }
#expect(throws: NetworkError.timeout) { try fetch() }
#expect(throws: Never.self) { try safeOperation() }Parameterized Tests
@Test("Validates inputs", arguments: zip(
["a", "b", "c"],
[1, 2, 3]
))
func testInputs(input: String, expected: Int) {
#expect(process(input) == expected)
}Warning: Multiple collections WITHOUT zip creates Cartesian product.
Async Testing
@Test func testAsync() async throws {
let result = try await fetchData()
#expect(!result.isEmpty)
}Confirmations
@Test func testCallback() async {
await confirmation("callback received") { confirm in
let sut = SomeType { confirm() }
sut.triggerCallback()
}
}Tags
extension Tag {
@Tag static var fast: Self
@Tag static var networking: Self
}
@Test(.tags(.fast, .networking))
func testNetworkCall() { }Common Pitfalls
1. Overusing `#require` — Use #expect for most checks 2. Forgetting state isolation — Each test gets a NEW instance 3. Accidental Cartesian product — Always use zip for paired inputs 4. Not using `.serialized` — Apply for thread-unsafe legacy tests
Common Mistakes
1. Overusing `#require` — #require is for preconditions only. Using it for normal assertions means the test stops at first failure instead of reporting all failures. Use #expect for assertions, #require only when subsequent assertions depend on the value.
2. Cartesian product bugs — @Test(arguments: [a, b], [c, d]) creates 4 combinations, not 2. Always use zip to pair arguments correctly: arguments: zip([a, b], [c, d]).
3. Forgetting state isolation — Swift Testing creates a new test instance per test method. BUT shared state between tests (static variables, singletons) still leak. Use dependency injection or clean up singletons between tests.
4. Parallel test conflicts — Swift Testing runs tests in parallel by default. Tests touching shared files, databases, or singletons will interfere. Use .serialized or isolation strategies.
5. Not using `async` naturally — Wrapping async operations in Task { } defeats the purpose. Use async/await directly in test function signature: @Test func testAsync() async throws { }.
6. Confirmation misuse — confirmation is for verifying callbacks were called. Using it for assertions is wrong. Use #expect for assertions, confirmation for callback counts.