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

Swift Testing

skill-notque-vexjoy-agent-swift-testing · by notque

Swift testing: XCTest, Swift Testing framework, async patterns.

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

Install

$ agentstack add skill-notque-vexjoy-agent-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-notque-vexjoy-agent-swift-testing)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo 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 Patterns

XCTest Basics

XCTest is Apple's foundational testing framework. Every test class inherits from XCTestCase and uses setUp/tearDown for lifecycle management.

import XCTest
@testable import MyApp

final class UserServiceTests: XCTestCase {
    var sut: UserService!
    var mockStore: MockUserStore!

    override func setUp() {
        super.setUp()
        mockStore = MockUserStore()
        sut = UserService(store: mockStore)
    }

    override func tearDown() {
        sut = nil
        mockStore = nil
        super.tearDown()
    }

    func testFetchUser_withValidID_returnsUser() {
        mockStore.stubbedUser = User(id: "1", name: "Alice")

        let user = sut.fetchUser(id: "1")

        XCTAssertNotNil(user)
        XCTAssertEqual(user?.name, "Alice")
    }

    func testFetchUser_withInvalidID_returnsNil() {
        mockStore.stubbedUser = nil

        let user = sut.fetchUser(id: "unknown")

        XCTAssertNil(user)
    }
}

Swift Testing Framework (Swift 5.9+)

The Swift Testing framework replaces XCTest with a more expressive, macro-driven approach. Use @Test for individual tests, #expect for assertions, and @Suite for grouping.

import Testing
@testable import MyApp

@Suite("User Service")
struct UserServiceTests {
    let mockStore = MockUserStore()

    @Test("fetches user by valid ID")
    func fetchValidUser() {
        mockStore.stubbedUser = User(id: "1", name: "Alice")
        let service = UserService(store: mockStore)

        let user = service.fetchUser(id: "1")

        #expect(user?.name == "Alice")
    }

    @Test("returns nil for unknown ID")
    func fetchUnknownUser() {
        mockStore.stubbedUser = nil
        let service = UserService(store: mockStore)

        #expect(service.fetchUser(id: "unknown") == nil)
    }
}

Parameterized Tests

Swift Testing supports parameterized tests natively, eliminating boilerplate for table-driven patterns.

@Test("validates email formats", arguments: [
    ("alice@example.com", true),
    ("bob@", false),
    ("", false),
    ("valid+tag@sub.domain.com", true),
])
func emailValidation(email: String, isValid: Bool) {
    #expect(EmailValidator.isValid(email) == isValid)
}

Async Testing

Async Test Methods (XCTest)

XCTest supports async test methods directly. For callback-based APIs, use XCTestExpectation.

// Direct async/await support
func testFetchProfile_async() async throws {
    let service = ProfileService(client: MockHTTPClient())

    let profile = try await service.fetchProfile(userID: "1")

    XCTAssertEqual(profile.name, "Alice")
}

// Callback-based APIs with expectations
func testFetchProfile_callback() {
    let expectation = expectation(description: "Profile fetched")
    let service = ProfileService(client: MockHTTPClient())

    service.fetchProfile(userID: "1") { result in
        switch result {
        case .success(let profile):
            XCTAssertEqual(profile.name, "Alice")
        case .failure(let error):
            XCTFail("Unexpected error: \(error)")
        }
        expectation.fulfill()
    }

    waitForExpectations(timeout: 5)
}

Async Tests with Swift Testing

@Test("fetches profile asynchronously")
func fetchProfileAsync() async throws {
    let service = ProfileService(client: MockHTTPClient())

    let profile = try await service.fetchProfile(userID: "1")

    #expect(profile.name == "Alice")
}

UI Testing

UI tests use XCUIApplication to interact with the app as a user would. Always prefer accessibility identifiers over text matching for resilient tests.

final class LoginUITests: XCTestCase {
    let app = XCUIApplication()

    override func setUp() {
        super.setUp()
        continueAfterFailure = false
        app.launchArguments = ["--uitesting"]
        app.launch()
    }

    func testSuccessfulLogin() {
        let emailField = app.textFields["login.emailField"]
        let passwordField = app.secureTextFields["login.passwordField"]
        let loginButton = app.buttons["login.submitButton"]

        emailField.tap()
        emailField.typeText("alice@example.com")

        passwordField.tap()
        passwordField.typeText("password123")

        loginButton.tap()

        let welcomeLabel = app.staticTexts["home.welcomeLabel"]
        XCTAssertTrue(welcomeLabel.waitForExistence(timeout: 5))
        XCTAssertEqual(welcomeLabel.label, "Welcome, Alice")
    }
}

Set accessibility identifiers in production code:

emailTextField.accessibilityIdentifier = "login.emailField"
passwordTextField.accessibilityIdentifier = "login.passwordField"
submitButton.accessibilityIdentifier = "login.submitButton"

Test Doubles: Protocol-Based Mocking

Swift's protocol-oriented design makes mocking straightforward. Define dependencies as protocols, then provide mock implementations in tests.

// Production protocol
protocol HTTPClient {
    func data(from url: URL) async throws -> (Data, URLResponse)
}

// Production implementation
struct URLSessionHTTPClient: HTTPClient {
    let session: URLSession

    func data(from url: URL) async throws -> (Data, URLResponse) {
        try await session.data(from: url)
    }
}

// Test double
final class MockHTTPClient: HTTPClient {
    var stubbedData: Data = Data()
    var stubbedResponse: URLResponse = HTTPURLResponse()
    var capturedURLs: [URL] = []

    func data(from url: URL) async throws -> (Data, URLResponse) {
        capturedURLs.append(url)
        return (stubbedData, stubbedResponse)
    }
}

Dependency Injection

Inject dependencies through initializers to make classes testable:

final class ProfileService {
    private let client: HTTPClient

    init(client: HTTPClient) {
        self.client = client
    }

    func fetchProfile(userID: String) async throws -> Profile {
        let url = URL(string: "https://api.example.com/users/\(userID)")!
        let (data, _) = try await client.data(from: url)
        return try JSONDecoder().decode(Profile.self, from: data)
    }
}

Key Conventions

  • One assertion per concept -- a single test can have multiple assertions if they verify the same logical behavior, but avoid testing unrelated things together.
  • Arrange-Act-Assert -- structure every test into setup, execution, and verification phases.
  • Name tests descriptively -- testFetchUser_withExpiredToken_throwsAuthError is better than testFetch2.
  • Prefer Swift Testing for new code -- use @Test and #expect when targeting Swift 5.9+; fall back to XCTest for older targets or UI tests.
  • Ensure test independence -- each test must be runnable in isolation; always produce self-contained test state.

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.