Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
johnrogers avatar

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-testing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs197
repo stars222
Last updatedJanuary 18, 2026
Repositoryjohnrogers/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

SKILL.mdMarkdownGitHub ↗

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

MacroUse 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

XCTestSwift 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 misuseconfirmation is for verifying callbacks were called. Using it for assertions is wrong. Use #expect for assertions, confirmation for callback counts.

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.