# Swift Testing Agent Skill Expert guidance for any AI coding tool that supports the [Agent Skills open format](https://agentskills.io/home) — Swift Testing framework, test doubles, fixtures, and testing best practices. ## Who this is for - Teams adopting Swift Testing framework who need modern testing patterns. - Developers writing unit tests, integration tests, or snapshot tests. - Anyone wanting reliable test infrastructure (mocks, stubs, spies, fixtures). - Teams migrating from XCTest to Swift Testing. ## How to Use This Skill ### Option A: Using skills.sh (recommended) Install this skill with a single command: ```bash npx skills add https://github.com/bocato/swift-testing-agent-skill --skill swift-testing ``` Then use the skill in your AI agent, for example: > Use the swift testing skill and help me write tests for the UserService class ### Option B: GitHub Copilot GitHub Copilot supports Agent Skills in VS Code, VS Code Insiders, and Copilot CLI. #### Project Skills (Recommended) Copy the `swift-testing/` folder to your repository's `.github/skills/` directory: ```bash # Clone this repo and copy the skill git clone https://github.com/bocato/swift-testing-agent-skill.git cp -r swift-testing-agent-skill/swift-testing .github/skills/ ``` Your project structure should look like: ``` your-project/ ├── .github/ │ └── skills/ │ └── swift-testing/ │ ├── SKILL.md │ └── references/ │ └── ... └── ... ``` #### Personal Skills For personal use across all projects, copy to your home directory: ```bash # Create personal skills directory if it doesn't exist mkdir -p ~/.copilot/skills # Copy the skill cp -r swift-testing-agent-skill/swift-testing ~/.copilot/skills/ ``` #### VS Code Configuration Ensure Agent Skills are enabled in VS Code settings: ```json { "chat.useAgentSkills": true } ``` Copilot will automatically discover and load the skill when relevant to your testing tasks. ### Option C: Claude Code Plugin #### Personal Usage To install this Skill for your personal use in Claude Code: 1. Add the marketplace: ```bash /plugin marketplace add bocato/swift-testing-agent-skill ``` 2. Install the Skill: ```bash /plugin install swift-testing@swift-testing-agent-skill ``` #### Project Configuration To automatically provide this Skill to everyone working in a repository, configure the repository's `.claude/settings.json`: ```json { "enabledPlugins": { "swift-testing@swift-testing-agent-skill": true }, "extraKnownMarketplaces": { "swift-testing-agent-skill": { "source": { "source": "github", "repo": "bocato/swift-testing-agent-skill" } } } } ``` When team members open the project, Claude Code will prompt them to install the Skill. ### Option D: Gemini CLI Gemini CLI supports custom instructions through `GEMINI.md` files or the `.gemini/` directory. #### Project Instructions (Recommended) Copy the skill content to your project's `.gemini/` directory: ```bash # Clone this repo git clone https://github.com/bocato/swift-testing-agent-skill.git # Create .gemini directory and copy the skill mkdir -p .gemini/skills cp -r swift-testing-agent-skill/swift-testing .gemini/skills/ ``` Your project structure should look like: ``` your-project/ ├── .gemini/ │ └── skills/ │ └── swift-testing/ │ ├── SKILL.md │ └── references/ │ └── ... └── ... ``` #### Personal Instructions For personal use across all projects, copy to your home directory: ```bash # Create personal Gemini skills directory mkdir -p ~/.gemini/skills # Copy the skill cp -r swift-testing-agent-skill/swift-testing ~/.gemini/skills/ ``` Gemini CLI will automatically discover skills in these locations when relevant to your testing tasks. ### Option E: Manual install 1) **Clone** this repository. 2) **Install or symlink** the `swift-testing/` folder following your tool's official skills installation docs (see links below). 3) **Use your AI tool** as usual and ask it to use the "swift-testing" skill for testing tasks. #### Where to Save Skills Follow your tool's official documentation, here are a few popular ones: - **Gemini CLI:** Use `.gemini/skills/` (project) or `~/.gemini/skills/` (personal) - **GitHub Copilot:** [About Agent Skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills) - Use `.github/skills/` (project) or `~/.copilot/skills/` (personal) - **Codex:** [Where to save skills](https://developers.openai.com/codex/skills/#where-to-save-skills) - **Claude:** [Using Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview#using-skills) - **Cursor:** [Enabling Skills](https://cursor.com/docs/context/skills#enabling-skills) **How to verify**: Your agent should reference the triage/playbook in `swift-testing/SKILL.md` and jump into the relevant reference file for your testing question or task. ## What This Skill Offers This skill gives your AI coding tool comprehensive Swift Testing guidance. It can: ### Guide Your Testing Decisions - Choose the right assertion (`#expect` vs `#require`) - Structure tests with Arrange-Act-Assert pattern - Apply F.I.R.S.T. principles (Fast, Isolated, Repeatable, Self-Validating, Timely) - Follow the test pyramid (80% unit, 15% integration, 5% UI) ### Write Proper Test Doubles - Understand Martin Fowler's test double taxonomy - Create Dummies, Fakes, Stubs, Spies, SpyingStubs, and Mocks - Choose between state verification and behavior verification - Place test doubles close to interfaces with `#if DEBUG` ### Create Maintainable Test Infrastructure - Build fixtures with sensible defaults - Place fixtures close to models - Handle dates deterministically - Organize test suites with tags and traits ### Test Various Scenarios - Write parameterized tests for multiple inputs - Test async code with proper patterns - Use confirmation for callback/delegate testing - Set up snapshot testing for UI regression ### Migrate from XCTest - Complete XCTest to Swift Testing migration guide - Assertion mapping (XCTAssertEqual -> #expect) - Setup/teardown patterns (setUp -> init) - Async test migration patterns ## What Makes This Skill Different **Practical Focus**: Based on real-world testing patterns from production codebases, focusing on what developers actually need. **Proper Taxonomy**: Uses Martin Fowler's official test double terminology, clarifying the confusion between "mocks" and "spies" in the Swift community. **Non-Opinionated**: Focuses on industry-standard best practices like F.I.R.S.T. principles and Arrange-Act-Assert, not architectural preferences. **Swift Testing Ready**: Covers the modern Swift Testing framework with `@Test`, `#expect`, `#require`, and `@Suite`. **Infrastructure Guidance**: Includes patterns for test doubles, fixtures, and their proper placement in your codebase. ## Skill Structure ``` swift-testing/ ├── SKILL.md # Main skill file with decision trees └── references/ ├── _index.md # Quick navigation for all topics ├── test-organization.md # Suites, tags, traits, parallel execution ├── parameterized-tests.md # Testing multiple inputs efficiently ├── async-testing.md # Async patterns, confirmation, timeouts ├── migration-xctest.md # XCTest to Swift Testing migration ├── test-doubles.md # Dummy, Fake, Stub, Spy, SpyingStub, Mock ├── fixtures.md # Fixture patterns and placement ├── integration-testing.md # Module interaction testing └── snapshot-testing.md # UI regression testing ``` ## Core Concepts ### Swift Testing Basics ```swift import Testing @Test("User can be created with valid data") func createUser() { let user = User(name: "Alice", age: 30) #expect(user.name == "Alice") #expect(user.age == 30) } ``` ### Arrange-Act-Assert ```swift @Test func calculateTotal() { // Given let cart = ShoppingCart() cart.add(Item(price: 10)) // When let total = cart.calculateTotal() // Then #expect(total == 10) } ``` ### Test Double (SpyingStub) ```swift #if DEBUG final class UserRepositorySpyingStub: UserRepositoryProtocol { // Spy private(set) var savedUsers: [User] = [] // Stub var usersToReturn: [User] = [] func save(_ user: User) async throws { savedUsers.append(user) } func getAll() async throws -> [User] { usersToReturn } } #endif ``` ### Fixture ```swift #if DEBUG extension User { static func fixture( id: UUID = UUID(), name: String = "Test User", email: String = "test@example.com" ) -> User { User(id: id, name: name, email: email) } } #endif ``` ## Contributing Contributions are welcome! This repository follows the [Agent Skills open format](https://agentskills.io/home), which has specific structural requirements. **We strongly recommend using AI assistance for contributions:** - Use the [skill-creator skill](https://github.com/anthropics/skills/tree/main/skills/skill-creator) with Claude to ensure proper formatting - This helps maintain the Agent Skills format and ensures your contribution works correctly with AI agents **Please read [CONTRIBUTING.md](CONTRIBUTING.md) for:** - How to use the skill-creator skill for contributions - Agent Skills format requirements - Quality standards and best practices - Pull request process This skill is maintained to reflect the latest Swift Testing best practices and will be updated as the framework evolves. ## License This skill is open-source and available under the MIT License. See [LICENSE](LICENSE) for details.