---
name: ios-testing
description: Testing practices for iOS 26 / Swift 6.2 clinic modular MVVM-C applications. Covers unit/UI/snapshot testing, protocol-based mocks, async actor isolation, and dependency-injected test architecture aligned with Domain protocols, App-target composition, and Data-owned I/O boundaries. Use when writing, reviewing, or refactoring tests for ios-* and swift-* clinic modules.
---

# iOS Testing Best Practices

Comprehensive testing guide for iOS and Swift applications, written at principal engineer level. Contains 44 rules across 8 categories, prioritized by impact to guide test architecture decisions, test authoring patterns, and CI infrastructure.


## Clinic Architecture Contract (iOS 26 / Swift 6.2)

All guidance in this skill assumes the clinic modular MVVM-C architecture:

- Feature modules import `Domain` + `DesignSystem` only (never `Data`, never sibling features)
- App target is the convergence point and owns `DependencyContainer`, concrete coordinators, and Route Shell wiring
- `Domain` stays pure Swift and defines models plus repository, `*Coordinating`, `ErrorRouting`, and `AppError` contracts
- `Data` owns SwiftData/network/sync/retry/background I/O and implements Domain protocols
- Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes
- ViewModels call repository protocols directly (no default use-case/interactor layer)

## When to Apply

Reference these guidelines when:
- Writing new unit tests or UI tests for iOS apps
- Designing testable architecture with dependency injection
- Testing async/await, actors, and Combine publishers
- Setting up snapshot testing or visual regression suites
- Configuring CI pipelines, test plans, and parallel execution

## Rule Categories by Priority

| Priority | Category | Impact | Prefix |
|----------|----------|--------|--------|
| 1 | Test Architecture & Testability | CRITICAL | `arch-` |
| 2 | Unit Testing Fundamentals | CRITICAL | `unit-` |
| 3 | Test Doubles & Isolation | HIGH | `mock-` |
| 4 | Async & Concurrency Testing | HIGH | `async-` |
| 5 | SwiftUI Testing | MEDIUM-HIGH | `swiftui-` |
| 6 | UI & Acceptance Testing | MEDIUM | `ui-` |
| 7 | Snapshot & Visual Testing | MEDIUM | `snap-` |
| 8 | Test Reliability & CI | LOW-MEDIUM | `ci-` |

## Quick Reference

### 1. Test Architecture & Testability (CRITICAL)

- [`arch-protocol-dependencies`](references/arch-protocol-dependencies.md) - Depend on protocols, not concrete types
- [`arch-constructor-injection`](references/arch-constructor-injection.md) - Use constructor injection over service locators
- [`arch-test-target-separation`](references/arch-test-target-separation.md) - Separate unit and UI test targets
- [`arch-testable-import`](references/arch-testable-import.md) - Use @testable import sparingly
- [`arch-single-responsibility-tests`](references/arch-single-responsibility-tests.md) - One assertion concept per test
- [`arch-arrange-act-assert`](references/arch-arrange-act-assert.md) - Structure tests as Arrange-Act-Assert

### 2. Unit Testing Fundamentals (CRITICAL)

- [`unit-swift-testing-framework`](references/unit-swift-testing-framework.md) - Use Swift Testing over XCTest for new tests
- [`unit-parameterized-tests`](references/unit-parameterized-tests.md) - Use parameterized tests for input variations
- [`unit-descriptive-test-names`](references/unit-descriptive-test-names.md) - Name tests after the behavior they verify
- [`unit-expect-over-assert`](references/unit-expect-over-assert.md) - Use #expect and #require over XCTAssert
- [`unit-require-preconditions`](references/unit-require-preconditions.md) - Use #require for test preconditions
- [`unit-test-suites`](references/unit-test-suites.md) - Organize related tests into suites
- [`unit-test-tags`](references/unit-test-tags.md) - Use tags to categorize cross-cutting tests

### 3. Test Doubles & Isolation (HIGH)

- [`mock-protocol-based-mocks`](references/mock-protocol-based-mocks.md) - Create mocks from protocols, not subclasses
- [`mock-spy-for-verification`](references/mock-spy-for-verification.md) - Use spies to verify interactions
- [`mock-stub-return-values`](references/mock-stub-return-values.md) - Use stubs for deterministic return values
- [`mock-avoid-over-mocking`](references/mock-avoid-over-mocking.md) - Avoid mocking value types and simple logic
- [`mock-fake-for-integration`](references/mock-fake-for-integration.md) - Use in-memory fakes for integration tests
- [`mock-dependency-container`](references/mock-dependency-container.md) - Use a dependency container for test configuration

### 4. Async & Concurrency Testing (HIGH)

- [`async-await-directly`](references/async-await-directly.md) - Await async functions directly in tests
- [`async-confirmation`](references/async-confirmation.md) - Use confirmation() for callback-based APIs
- [`async-mainactor-isolation`](references/async-mainactor-isolation.md) - Test MainActor-isolated code on MainActor
- [`async-actor-testing`](references/async-actor-testing.md) - Test actor state through async interface
- [`async-task-cancellation`](references/async-task-cancellation.md) - Test task cancellation paths explicitly

### 5. SwiftUI Testing (MEDIUM-HIGH)

- [`swiftui-test-observable-models`](references/swiftui-test-observable-models.md) - Test @Observable models as plain objects
- [`swiftui-environment-injection`](references/swiftui-environment-injection.md) - Inject environment dependencies for tests
- [`swiftui-preview-as-test`](references/swiftui-preview-as-test.md) - Use previews as visual smoke tests
- [`swiftui-view-model-extraction`](references/swiftui-view-model-extraction.md) - Extract logic from views into testable models
- [`swiftui-binding-testing`](references/swiftui-binding-testing.md) - Test binding behavior with @Bindable

### 6. UI & Acceptance Testing (MEDIUM)

- [`ui-accessibility-identifiers`](references/ui-accessibility-identifiers.md) - Use accessibility identifiers for element queries
- [`ui-page-object-pattern`](references/ui-page-object-pattern.md) - Encapsulate screens in page objects
- [`ui-launch-arguments`](references/ui-launch-arguments.md) - Configure test state via launch arguments
- [`ui-wait-for-elements`](references/ui-wait-for-elements.md) - Wait for elements instead of using sleep()
- [`ui-test-user-journeys`](references/ui-test-user-journeys.md) - Test complete user journeys, not individual screens
- [`ui-reset-state-between-tests`](references/ui-reset-state-between-tests.md) - Reset app state between UI tests

### 7. Snapshot & Visual Testing (MEDIUM)

- [`snap-swift-snapshot-testing`](references/snap-swift-snapshot-testing.md) - Use swift-snapshot-testing for visual regression
- [`snap-device-matrix`](references/snap-device-matrix.md) - Snapshot across device sizes and traits
- [`snap-named-references`](references/snap-named-references.md) - Use named snapshot references for clarity
- [`snap-inline-snapshots`](references/snap-inline-snapshots.md) - Use inline snapshots for non-image assertions

### 8. Test Reliability & CI (LOW-MEDIUM)

- [`ci-test-plans`](references/ci-test-plans.md) - Use Xcode Test Plans for environment configurations
- [`ci-parallel-execution`](references/ci-parallel-execution.md) - Enable parallel test execution
- [`ci-flaky-test-quarantine`](references/ci-flaky-test-quarantine.md) - Quarantine flaky tests instead of disabling them
- [`ci-deterministic-test-data`](references/ci-deterministic-test-data.md) - Use deterministic test data over random generation
- [`ci-coverage-thresholds`](references/ci-coverage-thresholds.md) - Set coverage thresholds for critical paths

## How to Use

Read individual reference files for detailed explanations and code examples:

- [Section definitions](references/_sections.md) - Category structure and impact levels
- [Rule template](assets/templates/_template.md) - Template for adding new rules

## Reference Files

| File | Description |
|------|-------------|
| [references/_sections.md](references/_sections.md) | Category definitions and ordering |
| [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules |
| [metadata.json](metadata.json) | Version and reference information |
