Use when writing unit tests, adopting Swift Testing framework, making tests run faster without simulator, architecting code for testability, testing async code reliably, or migrating from XCTest - covers @Test/@Suite macros, #expect/#require, parameterized tests, traits, tags, parallel execution, host-less testing
View on GitHubSelect agents to install to:
npx add-skill https://github.com/CharlesWiltgen/Axiom/blob/main/.claude-plugin/plugins/axiom/skills/axiom-swift-testing/SKILL.md -a claude-code --skill axiom-swift-testingInstallation paths:
.claude/skills/axiom-swift-testing/# Swift Testing
## Overview
Swift Testing is Apple's modern testing framework introduced at WWDC 2024. It uses Swift macros (`@Test`, `#expect`) instead of naming conventions, runs tests in parallel by default, and integrates seamlessly with Swift concurrency.
**Core principle**: Tests should be fast, reliable, and expressive. The fastest tests run without launching your app or simulator.
## The Speed Hierarchy
Tests run at dramatically different speeds depending on how they're configured:
| Configuration | Typical Time | Use Case |
|---------------|--------------|----------|
| `swift test` (Package) | ~0.1s | Pure logic, models, algorithms |
| Host Application: None | ~3s | Framework code, no UI dependencies |
| Bypass app launch | ~6s | App target but skip initialization |
| Full app launch | 20-60s | UI tests, integration tests |
**Key insight**: Move testable logic into Swift Packages or frameworks, then test with `swift test` or "None" host application.
---
## Building Blocks
### @Test Functions
```swift
import Testing
@Test func videoHasCorrectMetadata() {
let video = Video(named: "example.mp4")
#expect(video.duration == 120)
}
```
**Key differences from XCTest**:
- No `test` prefix required — `@Test` attribute is explicit
- Can be global functions, not just methods in a class
- Supports `async`, `throws`, and actor isolation
- Each test runs on a fresh instance of its containing suite
### #expect and #require
```swift
// Basic expectation — test continues on failure
#expect(result == expected)
#expect(array.isEmpty)
#expect(numbers.contains(42))
// Required expectation — test stops on failure
let user = try #require(await fetchUser(id: 123))
#expect(user.name == "Alice")
// Unwrap optionals safely
let first = try #require(items.first)
#expect(first.isValid)
```
**Why #expect is better than XCTAssert**:
- Captures source code and sub-values automatically
- Single macro handles all operators (==, >, contains, etc.)
- No need for specia