smithery.ai

swift-testing

Use when writing tests with Swift Testing (@Test, #expect, #require), migrating from XCTest, implementing async tests, or parameterizing tests.

First seen Mar 29, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,452 B
  • docs SUMMARY.md 70 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 5 installs

SKILL.md

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.
  1. 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]).
  1. 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.
  1. 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.
  1. 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 { }.
  1. Confirmation misuseconfirmation is for verifying callbacks were called. Using it for assertions is wrong. Use #expect for assertions, confirmation for callback counts.