[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FECSK8GSWC1FPBDHB8RNWK":3,"skill-same:01M6FECSK8GSWC1FPBDHB8RNWK":53},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":28,"frontMatter":29,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":35,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":37,"updatedAt":38,"install":39,"resources":52},"01M6FECSK8GSWC1FPBDHB8RNWK","ios-testing",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fpproenca\u002Fdot-skills\u002Fios-testing\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[23,24,25],"testing","ios","ios testing","2026-11-10 10:12:30",false,"# iOS Testing Best Practices\n\nComprehensive 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.\n\n\n## Clinic Architecture Contract (iOS 26 \u002F Swift 6.2)\n\nAll guidance in this skill assumes the clinic modular MVVM-C architecture:\n\n- Feature modules import `Domain` + `DesignSystem` only (never `Data`, never sibling features)\n- App target is the convergence point and owns `DependencyContainer`, concrete coordinators, and Route Shell wiring\n- `Domain` stays pure Swift and defines models plus repository, `*Coordinating`, `ErrorRouting`, and `AppError` contracts\n- `Data` owns SwiftData\u002Fnetwork\u002Fsync\u002Fretry\u002Fbackground I\u002FO and implements Domain protocols\n- Read\u002Fwrite flow defaults to stale-while-revalidate reads and optimistic queued writes\n- ViewModels call repository protocols directly (no default use-case\u002Finteractor layer)\n\n## When to Apply\n\nReference these guidelines when:\n- Writing new unit tests or UI tests for iOS apps\n- Designing testable architecture with dependency injection\n- Testing async\u002Fawait, actors, and Combine publishers\n- Setting up snapshot testing or visual regression suites\n- Configuring CI pipelines, test plans, and parallel execution\n\n## Rule Categories by Priority\n\n| Priority | Category | Impact | Prefix |\n|----------|----------|--------|--------|\n| 1 | Test Architecture & Testability | CRITICAL | `arch-` |\n| 2 | Unit Testing Fundamentals | CRITICAL | `unit-` |\n| 3 | Test Doubles & Isolation | HIGH | `mock-` |\n| 4 | Async & Concurrency Testing | HIGH | `async-` |\n| 5 | SwiftUI Testing | MEDIUM-HIGH | `swiftui-` |\n| 6 | UI & Acceptance Testing | MEDIUM | `ui-` |\n| 7 | Snapshot & Visual Testing | MEDIUM | `snap-` |\n| 8 | Test Reliability & CI | LOW-MEDIUM | `ci-` |\n\n## Quick Reference\n\n### 1. Test Architecture & Testability (CRITICAL)\n\n- [`arch-protocol-dependencies`](references\u002Farch-protocol-dependencies.md) - Depend on protocols, not concrete types\n- [`arch-constructor-injection`](references\u002Farch-constructor-injection.md) - Use constructor injection over service locators\n- [`arch-test-target-separation`](references\u002Farch-test-target-separation.md) - Separate unit and UI test targets\n- [`arch-testable-import`](references\u002Farch-testable-import.md) - Use @testable import sparingly\n- [`arch-single-responsibility-tests`](references\u002Farch-single-responsibility-tests.md) - One assertion concept per test\n- [`arch-arrange-act-assert`](references\u002Farch-arrange-act-assert.md) - Structure tests as Arrange-Act-Assert\n\n### 2. Unit Testing Fundamentals (CRITICAL)\n\n- [`unit-swift-testing-framework`](references\u002Funit-swift-testing-framework.md) - Use Swift Testing over XCTest for new tests\n- [`unit-parameterized-tests`](references\u002Funit-parameterized-tests.md) - Use parameterized tests for input variations\n- [`unit-descriptive-test-names`](references\u002Funit-descriptive-test-names.md) - Name tests after the behavior they verify\n- [`unit-expect-over-assert`](references\u002Funit-expect-over-assert.md) - Use #expect and #require over XCTAssert\n- [`unit-require-preconditions`](references\u002Funit-require-preconditions.md) - Use #require for test preconditions\n- [`unit-test-suites`](references\u002Funit-test-suites.md) - Organize related tests into suites\n- [`unit-test-tags`](references\u002Funit-test-tags.md) - Use tags to categorize cross-cutting tests\n\n### 3. Test Doubles & Isolation (HIGH)\n\n- [`mock-protocol-based-mocks`](references\u002Fmock-protocol-based-mocks.md) - Create mocks from protocols, not subclasses\n- [`mock-spy-for-verification`](references\u002Fmock-spy-for-verification.md) - Use spies to verify interactions\n- [`mock-stub-return-values`](references\u002Fmock-stub-return-values.md) - Use stubs for deterministic return values\n- [`mock-avoid-over-mocking`](references\u002Fmock-avoid-over-mocking.md) - Avoid mocking value types and simple logic\n- [`mock-fake-for-integration`](references\u002Fmock-fake-for-integration.md) - Use in-memory fakes for integration tests\n- [`mock-dependency-container`](references\u002Fmock-dependency-container.md) - Use a dependency container for test configuration\n\n### 4. Async & Concurrency Testing (HIGH)\n\n- [`async-await-directly`](references\u002Fasync-await-directly.md) - Await async functions directly in tests\n- [`async-confirmation`](references\u002Fasync-confirmation.md) - Use confirmation() for callback-based APIs\n- [`async-mainactor-isolation`](references\u002Fasync-mainactor-isolation.md) - Test MainActor-isolated code on MainActor\n- [`async-actor-testing`](references\u002Fasync-actor-testing.md) - Test actor state through async interface\n- [`async-task-cancellation`](references\u002Fasync-task-cancellation.md) - Test task cancellation paths explicitly\n\n### 5. SwiftUI Testing (MEDIUM-HIGH)\n\n- [`swiftui-test-observable-models`](references\u002Fswiftui-test-observable-models.md) - Test @Observable models as plain objects\n- [`swiftui-environment-injection`](references\u002Fswiftui-environment-injection.md) - Inject environment dependencies for tests\n- [`swiftui-preview-as-test`](references\u002Fswiftui-preview-as-test.md) - Use previews as visual smoke tests\n- [`swiftui-view-model-extraction`](references\u002Fswiftui-view-model-extraction.md) - Extract logic from views into testable models\n- [`swiftui-binding-testing`](references\u002Fswiftui-binding-testing.md) - Test binding behavior with @Bindable\n\n### 6. UI & Acceptance Testing (MEDIUM)\n\n- [`ui-accessibility-identifiers`](references\u002Fui-accessibility-identifiers.md) - Use accessibility identifiers for element queries\n- [`ui-page-object-pattern`](references\u002Fui-page-object-pattern.md) - Encapsulate screens in page objects\n- [`ui-launch-arguments`](references\u002Fui-launch-arguments.md) - Configure test state via launch arguments\n- [`ui-wait-for-elements`](references\u002Fui-wait-for-elements.md) - Wait for elements instead of using sleep()\n- [`ui-test-user-journeys`](references\u002Fui-test-user-journeys.md) - Test complete user journeys, not individual screens\n- [`ui-reset-state-between-tests`](references\u002Fui-reset-state-between-tests.md) - Reset app state between UI tests\n\n### 7. Snapshot & Visual Testing (MEDIUM)\n\n- [`snap-swift-snapshot-testing`](references\u002Fsnap-swift-snapshot-testing.md) - Use swift-snapshot-testing for visual regression\n- [`snap-device-matrix`](references\u002Fsnap-device-matrix.md) - Snapshot across device sizes and traits\n- [`snap-named-references`](references\u002Fsnap-named-references.md) - Use named snapshot references for clarity\n- [`snap-inline-snapshots`](references\u002Fsnap-inline-snapshots.md) - Use inline snapshots for non-image assertions\n\n### 8. Test Reliability & CI (LOW-MEDIUM)\n\n- [`ci-test-plans`](references\u002Fci-test-plans.md) - Use Xcode Test Plans for environment configurations\n- [`ci-parallel-execution`](references\u002Fci-parallel-execution.md) - Enable parallel test execution\n- [`ci-flaky-test-quarantine`](references\u002Fci-flaky-test-quarantine.md) - Quarantine flaky tests instead of disabling them\n- [`ci-deterministic-test-data`](references\u002Fci-deterministic-test-data.md) - Use deterministic test data over random generation\n- [`ci-coverage-thresholds`](references\u002Fci-coverage-thresholds.md) - Set coverage thresholds for critical paths\n\n## How to Use\n\nRead individual reference files for detailed explanations and code examples:\n\n- [Section definitions](references\u002F_sections.md) - Category structure and impact levels\n- [Rule template](assets\u002Ftemplates\u002F_template.md) - Template for adding new rules\n\n## Reference Files\n\n| File | Description |\n|------|-------------|\n| [references\u002F_sections.md](references\u002F_sections.md) | Category definitions and ordering |\n| [assets\u002Ftemplates\u002F_template.md](assets\u002Ftemplates\u002F_template.md) | Template for new rules |\n| [metadata.json](metadata.json) | Version and reference information |\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fpproenca\u002Fdot-skills\u002Fios-testing",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":40,"prompt":50,"zipAvailable":51},[41,44,47],{"tool":42,"command":43},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill ios-testing",{"tool":45,"command":46},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill ios-testing",{"tool":48,"command":49},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill ios-testing","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fpproenca\u002Fdot-skills\u002Fios-testing\u002FSKILL.md",true,[],[54,66,76,85,91,98],{"skillNo":55,"name":56,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":62,"publishedAt":26},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[59],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[63,64,65],"model","model hierarchy","model hierarchy skill",{"skillNo":67,"name":68,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":72,"publishedAt":26},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[71],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},[73,74,75],"MCP","zoom","zoom mcp",{"skillNo":77,"name":78,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":26},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[82,83,84,74],"sdk","zoom apps sdk","apps",{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":26},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[87],{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":97,"publishedAt":26},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[96],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},[93],{"skillNo":99,"name":100,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":26},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[100]]