AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Swift Testing

skill-jeremieb-swift-unit-test-instructions-swift-testing · by jeremieb

Writes unit tests and UI tests for Swift, SwiftUI, and UIKit projects following enterprise or indie testing standards. Use when user says "write tests", "add unit tests", "test this code", "create test cases", "add XCTest", "write Swift Testing tests", "help me test this", or "add tests for". Applies enterprise or indie standard from references/ based on project CLAUDE.md config.

No reviews yet
0 installs
8 views
0.0% view→install

Install

$ agentstack add skill-jeremieb-swift-unit-test-instructions-swift-testing

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jeremieb-swift-unit-test-instructions-swift-testing)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
5mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Swift Testing? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Swift Testing

Instructions

Step 1: Determine Testing Mode

Check CLAUDE.md for Testing Mode:

  • enterprise → consult references/enterprise.md for strict rules
  • indie → consult references/indie.md for pragmatic rules
  • If not set: ask the user which mode applies

Step 2: Identify What to Test

Ask if not already clear:

  • Which type / function / feature needs tests?
  • What is the expected behavior (not implementation)?
  • Are there async operations?
  • Are there existing mocks or does the skill need to create them?

Always test:

  • ViewModels (state changes, actions, error states)
  • Services and Repositories (business logic, data transformations)
  • Formatters, validators, utilities
  • Async flows end-to-end (with mocked dependencies)
  • Edge cases and error paths

Never test:

  • Private implementation details
  • SwiftUI view tree structure or layout positions
  • UIViewController internal wiring

Step 3: Choose the Framework

| Scenario | Framework | |---|---| | New unit tests (Swift 5.9+, iOS 16+) | Swift Testing (@Test, #expect) | | Legacy or team convention on XCTest | XCTest (XCTestCase, XCTAssert*) | | UI / end-to-end tests | XCTest + XCUITest | | Async unit tests | Both support async — use await |

Do NOT mix Swift Testing and XCTest in the same test target.

Step 4: Write Tests

Naming (both frameworks):

test_when__should_()

Structure — Swift Testing:

import Testing
@testable import MyApp

@MainActor
struct LoginViewModelTests {

    @Test func test_when_credentialsAreValid_should_setIsLoggedIn() async throws {
        // Arrange
        let authService = MockAuthService(willSucceed: true)
        let sut = LoginViewModel(authService: authService)

        // Act
        await sut.login(email: "user@example.com", password: "secret")

        // Assert
        #expect(sut.isLoggedIn == true)
        #expect(sut.error == nil)
    }

    @Test func test_when_credentialsAreInvalid_should_setError() async throws {
        // Arrange
        let authService = MockAuthService(willSucceed: false)
        let sut = LoginViewModel(authService: authService)

        // Act
        await sut.login(email: "bad@example.com", password: "wrong")

        // Assert
        #expect(sut.isLoggedIn == false)
        #expect(sut.error != nil)
    }
}

Structure — XCTest:

import XCTest
@testable import MyApp

@MainActor
final class LoginViewModelTests: XCTestCase {

    func test_when_credentialsAreValid_should_setIsLoggedIn() async throws {
        // Arrange
        let authService = MockAuthService(willSucceed: true)
        let sut = LoginViewModel(authService: authService)

        // Act
        await sut.login(email: "user@example.com", password: "secret")

        // Assert
        XCTAssertTrue(sut.isLoggedIn)
        XCTAssertNil(sut.error)
    }
}

Step 5: Generate Mocks

Always generate a mock alongside any test that needs one:

// Always inject via protocol, never use real implementations in unit tests
final class MockAuthService: AuthServiceProtocol {
    let willSucceed: Bool
    private(set) var loginCallCount = 0

    init(willSucceed: Bool) {
        self.willSucceed = willSucceed
    }

    func login(email: String, password: String) async throws -> User {
        loginCallCount += 1
        if willSucceed {
            return User(id: "1", email: email)
        } else {
            throw AuthError.invalidCredentials
        }
    }
}

Step 6: Determinism Checklist

Before finalizing, verify every test:

  • [ ] No real network calls
  • [ ] No sleep() or polling
  • [ ] No shared global state between tests
  • [ ] No real time/date dependency (inject Date or a clock protocol)
  • [ ] Fresh sut instance per test
  • [ ] setUp/tearDown only when truly necessary

Examples

Example 1: ViewModel with async fetch

User says: "Write tests for my ProductListViewModel that fetches products from an API"

Actions:

  1. Read ProductListViewModel.swift to understand state and dependencies
  2. Identify the ProductRepositoryProtocol or create it if missing
  3. Generate MockProductRepository with stubbable results
  4. Write tests: empty state, loaded state, error state, loading indicator

Example 2: Data transformation

User says: "Test my PriceFormatter that converts cents to currency string"

Actions:

  1. Read PriceFormatter.swift
  2. Write Swift Testing @Test functions for: zero cents, typical value, large value, locale edge cases

Troubleshooting

Async tests fail intermittently: You are using sleep() or polling. Replace with async/await and mocked async dependencies that resolve immediately.

Tests break on refactoring: You are testing implementation details (private properties, internal call counts). Refocus on observable output state only.

ViewModel is untestable: Dependencies are created inside the type (NetworkService()). Inject them via init. This is an architecture issue — see swift-architecture-audit skill.

"Cannot find type X in scope": Add @testable import YourModule at the top of the test file.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.