buildanything 1.7.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +9 -3
- package/CHANGELOG.md +112 -0
- package/README.md +2 -2
- package/agents/a11y-architect.md +166 -0
- package/agents/business-model.md +80 -29
- package/agents/code-architect.md +75 -0
- package/agents/code-reviewer.md +255 -0
- package/agents/code-simplifier.md +64 -0
- package/agents/design-brand-guardian.md +293 -53
- package/agents/design-critic.md +139 -0
- package/agents/design-inclusive-visuals-specialist.md +6 -19
- package/agents/design-ui-designer.md +335 -56
- package/agents/design-ux-architect.md +403 -55
- package/agents/design-ux-researcher.md +264 -49
- package/agents/engineering-ai-engineer.md +26 -36
- package/agents/engineering-backend-architect.md +185 -36
- package/agents/engineering-data-engineer.md +225 -43
- package/agents/engineering-devops-automator.md +227 -74
- package/agents/engineering-frontend-developer.md +210 -34
- package/agents/engineering-mobile-app-builder.md +6 -1
- package/agents/engineering-rapid-prototyper.md +30 -9
- package/agents/engineering-security-engineer.md +263 -61
- package/agents/engineering-senior-developer.md +128 -19
- package/agents/engineering-sre.md +84 -0
- package/agents/engineering-technical-writer.md +285 -41
- package/agents/feature-intel.md +110 -0
- package/agents/ios-app-review-guardian.md +66 -0
- package/agents/ios-foundation-models-specialist.md +64 -0
- package/agents/ios-storekit-specialist.md +59 -0
- package/agents/ios-swift-architect.md +129 -0
- package/agents/ios-swift-search.md +137 -0
- package/agents/ios-swift-ui-design.md +136 -0
- package/agents/marketing-app-store-optimizer.md +246 -64
- package/agents/planner.md +216 -0
- package/agents/pr-test-analyzer.md +63 -0
- package/agents/product-feedback-synthesizer.md +8 -2
- package/agents/refactor-cleaner.md +102 -0
- package/agents/security-reviewer.md +128 -0
- package/agents/silent-failure-hunter.md +54 -0
- package/agents/swift-build-resolver.md +119 -0
- package/agents/swift-reviewer.md +112 -0
- package/agents/tech-feasibility.md +21 -1
- package/agents/testing-api-tester.md +236 -59
- package/agents/testing-evidence-collector.md +26 -1
- package/agents/testing-performance-benchmarker.md +21 -1
- package/agents/testing-reality-checker.md +6 -1
- package/agents/visual-research.md +116 -0
- package/bin/adapters/cycle-counter-tool.ts +155 -0
- package/bin/adapters/scribe-tool.ts +71 -0
- package/bin/adapters/state-save-tool.ts +130 -0
- package/bin/adapters/write-lease-tool.ts +127 -0
- package/bin/buildanything-runtime.js +15 -0
- package/bin/buildanything-runtime.ts +328 -0
- package/bin/setup.js +83 -8
- package/commands/add-feature.md +2 -0
- package/commands/build.md +752 -332
- package/commands/fix.md +65 -0
- package/commands/self-check.md +121 -0
- package/commands/setup.md +114 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +69 -0
- package/docs/migration/agents.yaml +729 -0
- package/docs/migration/phase-graph.yaml +1088 -0
- package/docs/migration/sdk-host-compat.md +18 -0
- package/hooks/compile-writer-owner-cache.ts +171 -0
- package/hooks/hooks.json +36 -0
- package/hooks/pre-tool-use +19 -0
- package/hooks/pre-tool-use.ts +776 -0
- package/hooks/record-mode-transitions.ts +178 -0
- package/hooks/session-start +89 -2
- package/hooks/subagent-start +17 -0
- package/hooks/subagent-start.ts +471 -0
- package/hooks/subagent-stop +17 -0
- package/hooks/subagent-stop.ts +153 -0
- package/package.json +28 -5
- package/protocols/architecture-schema.md +171 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/decision-log.md +131 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +234 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +337 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/launch-readiness.md +258 -0
- package/protocols/metric-loop.md +153 -0
- package/protocols/smoke-test.md +118 -0
- package/protocols/state-schema.json +388 -0
- package/protocols/state-schema.md +172 -0
- package/protocols/verify.md +127 -0
- package/protocols/visual-dna.md +185 -0
- package/protocols/web-phase-branches.md +351 -0
- package/skills/ios/_VENDORED.md +62 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/app-store-connect-metadata/SKILL.md +148 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/asc-privacy-manifest/SKILL.md +350 -0
- package/skills/ios/hig-components-content/SKILL.md +86 -0
- package/skills/ios/hig-components-content/references/activity-views.md +79 -0
- package/skills/ios/hig-components-content/references/charts.md +180 -0
- package/skills/ios/hig-components-content/references/collections.md +48 -0
- package/skills/ios/hig-components-content/references/color-wells.md +42 -0
- package/skills/ios/hig-components-content/references/image-views.md +82 -0
- package/skills/ios/hig-components-content/references/image-wells.md +34 -0
- package/skills/ios/hig-components-content/references/lockups.md +78 -0
- package/skills/ios/hig-components-content/references/web-views.md +36 -0
- package/skills/ios/hig-components-controls/SKILL.md +88 -0
- package/skills/ios/hig-components-controls/references/combo-boxes.md +40 -0
- package/skills/ios/hig-components-controls/references/controls.md +112 -0
- package/skills/ios/hig-components-controls/references/gauges.md +74 -0
- package/skills/ios/hig-components-controls/references/labels.md +92 -0
- package/skills/ios/hig-components-controls/references/pickers.md +128 -0
- package/skills/ios/hig-components-controls/references/rating-indicators.md +38 -0
- package/skills/ios/hig-components-controls/references/segmented-controls.md +94 -0
- package/skills/ios/hig-components-controls/references/sliders.md +92 -0
- package/skills/ios/hig-components-controls/references/steppers.md +40 -0
- package/skills/ios/hig-components-controls/references/text-fields.md +88 -0
- package/skills/ios/hig-components-controls/references/text-views.md +56 -0
- package/skills/ios/hig-components-controls/references/toggles.md +127 -0
- package/skills/ios/hig-components-controls/references/token-fields.md +48 -0
- package/skills/ios/hig-components-controls/references/virtual-keyboards.md +156 -0
- package/skills/ios/hig-components-dialogs/SKILL.md +76 -0
- package/skills/ios/hig-components-dialogs/references/action-sheets.md +74 -0
- package/skills/ios/hig-components-dialogs/references/alerts.md +158 -0
- package/skills/ios/hig-components-dialogs/references/digit-entry-views.md +32 -0
- package/skills/ios/hig-components-dialogs/references/popovers.md +81 -0
- package/skills/ios/hig-components-dialogs/references/sheets.md +157 -0
- package/skills/ios/hig-components-layout/SKILL.md +99 -0
- package/skills/ios/hig-components-layout/references/boxes.md +48 -0
- package/skills/ios/hig-components-layout/references/column-views.md +44 -0
- package/skills/ios/hig-components-layout/references/lists-and-tables.md +99 -0
- package/skills/ios/hig-components-layout/references/ornaments.md +56 -0
- package/skills/ios/hig-components-layout/references/outline-views.md +64 -0
- package/skills/ios/hig-components-layout/references/panels.md +75 -0
- package/skills/ios/hig-components-layout/references/scroll-views.md +123 -0
- package/skills/ios/hig-components-layout/references/sidebars.md +109 -0
- package/skills/ios/hig-components-layout/references/split-views.md +110 -0
- package/skills/ios/hig-components-layout/references/tab-bars.md +173 -0
- package/skills/ios/hig-components-layout/references/tab-views.md +68 -0
- package/skills/ios/hig-components-layout/references/windows.md +188 -0
- package/skills/ios/hig-components-menus/SKILL.md +81 -0
- package/skills/ios/hig-components-menus/references/action-button.md +61 -0
- package/skills/ios/hig-components-menus/references/buttons.md +261 -0
- package/skills/ios/hig-components-menus/references/context-menus.md +105 -0
- package/skills/ios/hig-components-menus/references/disclosure-controls.md +84 -0
- package/skills/ios/hig-components-menus/references/dock-menus.md +40 -0
- package/skills/ios/hig-components-menus/references/edit-menus.md +88 -0
- package/skills/ios/hig-components-menus/references/menus.md +171 -0
- package/skills/ios/hig-components-menus/references/pop-up-buttons.md +70 -0
- package/skills/ios/hig-components-menus/references/pull-down-buttons.md +77 -0
- package/skills/ios/hig-components-menus/references/the-menu-bar.md +303 -0
- package/skills/ios/hig-components-menus/references/toolbars.md +256 -0
- package/skills/ios/hig-components-search/SKILL.md +68 -0
- package/skills/ios/hig-components-search/references/page-controls.md +120 -0
- package/skills/ios/hig-components-search/references/path-controls.md +40 -0
- package/skills/ios/hig-components-search/references/search-fields.md +189 -0
- package/skills/ios/hig-components-status/SKILL.md +80 -0
- package/skills/ios/hig-components-status/references/activity-rings.md +105 -0
- package/skills/ios/hig-components-status/references/progress-indicators.md +116 -0
- package/skills/ios/hig-components-status/references/status-bars.md +38 -0
- package/skills/ios/hig-components-system/SKILL.md +88 -0
- package/skills/ios/hig-components-system/references/app-clips.md +387 -0
- package/skills/ios/hig-components-system/references/app-shortcuts.md +114 -0
- package/skills/ios/hig-components-system/references/complications.md +425 -0
- package/skills/ios/hig-components-system/references/home-screen-quick-actions.md +42 -0
- package/skills/ios/hig-components-system/references/live-activities.md +442 -0
- package/skills/ios/hig-components-system/references/notifications.md +153 -0
- package/skills/ios/hig-components-system/references/top-shelf.md +135 -0
- package/skills/ios/hig-components-system/references/watch-faces.md +40 -0
- package/skills/ios/hig-components-system/references/widgets.md +517 -0
- package/skills/ios/hig-foundations/SKILL.md +98 -0
- package/skills/ios/hig-foundations/references/accessibility.md +291 -0
- package/skills/ios/hig-foundations/references/app-icons.md +210 -0
- package/skills/ios/hig-foundations/references/branding.md +44 -0
- package/skills/ios/hig-foundations/references/color.md +274 -0
- package/skills/ios/hig-foundations/references/dark-mode.md +116 -0
- package/skills/ios/hig-foundations/references/icons.md +263 -0
- package/skills/ios/hig-foundations/references/images.md +176 -0
- package/skills/ios/hig-foundations/references/immersive-experiences.md +174 -0
- package/skills/ios/hig-foundations/references/inclusion.md +189 -0
- package/skills/ios/hig-foundations/references/layout.md +425 -0
- package/skills/ios/hig-foundations/references/materials.md +238 -0
- package/skills/ios/hig-foundations/references/motion.md +103 -0
- package/skills/ios/hig-foundations/references/privacy.md +231 -0
- package/skills/ios/hig-foundations/references/right-to-left.md +206 -0
- package/skills/ios/hig-foundations/references/sf-symbols.md +310 -0
- package/skills/ios/hig-foundations/references/spatial-layout.md +142 -0
- package/skills/ios/hig-foundations/references/typography.md +1146 -0
- package/skills/ios/hig-foundations/references/writing.md +91 -0
- package/skills/ios/hig-inputs/SKILL.md +94 -0
- package/skills/ios/hig-inputs/references/apple-pencil-and-scribble.md +148 -0
- package/skills/ios/hig-inputs/references/camera-control.md +107 -0
- package/skills/ios/hig-inputs/references/digital-crown.md +83 -0
- package/skills/ios/hig-inputs/references/eyes.md +120 -0
- package/skills/ios/hig-inputs/references/focus-and-selection.md +120 -0
- package/skills/ios/hig-inputs/references/game-controls.md +156 -0
- package/skills/ios/hig-inputs/references/gestures.md +208 -0
- package/skills/ios/hig-inputs/references/gyro-and-accelerometer.md +40 -0
- package/skills/ios/hig-inputs/references/keyboards.md +234 -0
- package/skills/ios/hig-inputs/references/nearby-interactions.md +70 -0
- package/skills/ios/hig-inputs/references/pointing-devices.md +237 -0
- package/skills/ios/hig-inputs/references/remotes.md +67 -0
- package/skills/ios/hig-inputs/references/spatial-interactions.md +70 -0
- package/skills/ios/hig-patterns/SKILL.md +104 -0
- package/skills/ios/hig-patterns/references/charting-data.md +81 -0
- package/skills/ios/hig-patterns/references/collaboration-and-sharing.md +86 -0
- package/skills/ios/hig-patterns/references/drag-and-drop.md +134 -0
- package/skills/ios/hig-patterns/references/entering-data.md +69 -0
- package/skills/ios/hig-patterns/references/feedback.md +67 -0
- package/skills/ios/hig-patterns/references/file-management.md +135 -0
- package/skills/ios/hig-patterns/references/going-full-screen.md +79 -0
- package/skills/ios/hig-patterns/references/launching.md +81 -0
- package/skills/ios/hig-patterns/references/live-viewing-apps.md +79 -0
- package/skills/ios/hig-patterns/references/loading.md +59 -0
- package/skills/ios/hig-patterns/references/managing-accounts.md +107 -0
- package/skills/ios/hig-patterns/references/managing-notifications.md +99 -0
- package/skills/ios/hig-patterns/references/modality.md +82 -0
- package/skills/ios/hig-patterns/references/multitasking.md +131 -0
- package/skills/ios/hig-patterns/references/offering-help.md +117 -0
- package/skills/ios/hig-patterns/references/onboarding.md +69 -0
- package/skills/ios/hig-patterns/references/playing-audio.md +124 -0
- package/skills/ios/hig-patterns/references/playing-haptics.md +280 -0
- package/skills/ios/hig-patterns/references/playing-video.md +180 -0
- package/skills/ios/hig-patterns/references/printing.md +50 -0
- package/skills/ios/hig-patterns/references/ratings-and-reviews.md +48 -0
- package/skills/ios/hig-patterns/references/searching.md +70 -0
- package/skills/ios/hig-patterns/references/settings.md +84 -0
- package/skills/ios/hig-patterns/references/undo-and-redo.md +58 -0
- package/skills/ios/hig-patterns/references/workouts.md +76 -0
- package/skills/ios/hig-platforms/SKILL.md +84 -0
- package/skills/ios/hig-platforms/references/designing-for-games.md +159 -0
- package/skills/ios/hig-platforms/references/designing-for-ios.md +66 -0
- package/skills/ios/hig-platforms/references/designing-for-ipados.md +64 -0
- package/skills/ios/hig-platforms/references/designing-for-macos.md +70 -0
- package/skills/ios/hig-platforms/references/designing-for-tvos.md +68 -0
- package/skills/ios/hig-platforms/references/designing-for-visionos.md +85 -0
- package/skills/ios/hig-platforms/references/designing-for-watchos.md +74 -0
- package/skills/ios/hig-project-context/SKILL.md +133 -0
- package/skills/ios/hig-technologies/SKILL.md +107 -0
- package/skills/ios/hig-technologies/references/airplay.md +125 -0
- package/skills/ios/hig-technologies/references/always-on.md +62 -0
- package/skills/ios/hig-technologies/references/apple-pay.md +441 -0
- package/skills/ios/hig-technologies/references/augmented-reality.md +247 -0
- package/skills/ios/hig-technologies/references/carekit.md +224 -0
- package/skills/ios/hig-technologies/references/carplay.md +119 -0
- package/skills/ios/hig-technologies/references/game-center.md +343 -0
- package/skills/ios/hig-technologies/references/generative-ai.md +110 -0
- package/skills/ios/hig-technologies/references/healthkit.md +120 -0
- package/skills/ios/hig-technologies/references/homekit.md +343 -0
- package/skills/ios/hig-technologies/references/icloud.md +52 -0
- package/skills/ios/hig-technologies/references/id-verifier.md +73 -0
- package/skills/ios/hig-technologies/references/imessage-apps-and-stickers.md +105 -0
- package/skills/ios/hig-technologies/references/in-app-purchase.md +263 -0
- package/skills/ios/hig-technologies/references/live-photos.md +54 -0
- package/skills/ios/hig-technologies/references/mac-catalyst.md +216 -0
- package/skills/ios/hig-technologies/references/machine-learning.md +394 -0
- package/skills/ios/hig-technologies/references/maps.md +221 -0
- package/skills/ios/hig-technologies/references/nfc.md +51 -0
- package/skills/ios/hig-technologies/references/photo-editing.md +40 -0
- package/skills/ios/hig-technologies/references/researchkit.md +134 -0
- package/skills/ios/hig-technologies/references/shareplay.md +142 -0
- package/skills/ios/hig-technologies/references/shazamkit.md +47 -0
- package/skills/ios/hig-technologies/references/sign-in-with-apple.md +288 -0
- package/skills/ios/hig-technologies/references/siri.md +523 -0
- package/skills/ios/hig-technologies/references/tap-to-pay-on-iphone.md +208 -0
- package/skills/ios/hig-technologies/references/voiceover.md +90 -0
- package/skills/ios/hig-technologies/references/wallet.md +420 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +107 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-actor-persistence/SKILL.md +143 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/ios/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-design-tokens/SKILL.md +475 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
- package/skills/ios/writing-for-interfaces/SKILL.md +75 -0
- package/skills/web/accessibility/SKILL.md +146 -0
- package/skills/web/aceternity-ui/SKILL.md +719 -0
- package/skills/web/aceternity-ui/metadata.json +10 -0
- package/skills/web/api-design/SKILL.md +523 -0
- package/skills/web/chart-accessibility/SKILL.md +332 -0
- package/skills/web/composition-patterns/AGENTS.md +946 -0
- package/skills/web/composition-patterns/README.md +60 -0
- package/skills/web/composition-patterns/SKILL.md +89 -0
- package/skills/web/composition-patterns/metadata.json +11 -0
- package/skills/web/composition-patterns/rules/_sections.md +29 -0
- package/skills/web/composition-patterns/rules/_template.md +24 -0
- package/skills/web/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/web/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/web/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/web/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/web/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/web/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/web/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/web/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/web/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/web/database-migrations/SKILL.md +429 -0
- package/skills/web/deployment-patterns/SKILL.md +427 -0
- package/skills/web/docker-patterns/SKILL.md +364 -0
- package/skills/web/e2e-testing/SKILL.md +326 -0
- package/skills/web/lighthouse-ci/SKILL.md +361 -0
- package/skills/web/mcp-server-patterns/SKILL.md +69 -0
- package/skills/web/next-best-practices/SKILL.md +153 -0
- package/skills/web/next-best-practices/async-patterns.md +87 -0
- package/skills/web/next-best-practices/bundling.md +180 -0
- package/skills/web/next-best-practices/data-patterns.md +297 -0
- package/skills/web/next-best-practices/debug-tricks.md +105 -0
- package/skills/web/next-best-practices/directives.md +73 -0
- package/skills/web/next-best-practices/error-handling.md +227 -0
- package/skills/web/next-best-practices/file-conventions.md +140 -0
- package/skills/web/next-best-practices/font.md +245 -0
- package/skills/web/next-best-practices/functions.md +108 -0
- package/skills/web/next-best-practices/hydration-error.md +91 -0
- package/skills/web/next-best-practices/image.md +173 -0
- package/skills/web/next-best-practices/metadata.md +301 -0
- package/skills/web/next-best-practices/parallel-routes.md +287 -0
- package/skills/web/next-best-practices/route-handlers.md +146 -0
- package/skills/web/next-best-practices/rsc-boundaries.md +159 -0
- package/skills/web/next-best-practices/runtime-selection.md +39 -0
- package/skills/web/next-best-practices/scripts.md +141 -0
- package/skills/web/next-best-practices/self-hosting.md +371 -0
- package/skills/web/next-best-practices/suspense-boundaries.md +67 -0
- package/skills/web/next-cache-components/SKILL.md +411 -0
- package/skills/web/postgres-best-practices/SKILL.md +14 -0
- package/skills/web/postgres-best-practices/references/schema-design.md +9 -0
- package/skills/web/react-best-practices/AGENTS.md +3810 -0
- package/skills/web/react-best-practices/README.md +123 -0
- package/skills/web/react-best-practices/SKILL.md +149 -0
- package/skills/web/react-best-practices/metadata.json +15 -0
- package/skills/web/react-best-practices/rules/_sections.md +46 -0
- package/skills/web/react-best-practices/rules/_template.md +28 -0
- package/skills/web/react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/skills/web/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/web/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/web/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/web/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/web/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/skills/web/react-best-practices/rules/async-defer-await.md +82 -0
- package/skills/web/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/web/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/web/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/web/react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/skills/web/react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/skills/web/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/web/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/web/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/web/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/web/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/web/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/web/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/web/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/web/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/web/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/web/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/web/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/web/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/web/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/web/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/web/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/web/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/web/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/web/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/web/react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/skills/web/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/web/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/web/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/web/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/web/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/web/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/web/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/web/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/web/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/web/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/web/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/web/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/web/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/web/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/web/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/web/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/web/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/web/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/web/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/web/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/web/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/web/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/web/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/web/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/web/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/web/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/web/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/web/react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/skills/web/react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/skills/web/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/web/react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/skills/web/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/web/seo/SKILL.md +154 -0
- package/skills/web/web-design-guidelines/SKILL.md +39 -0
- package/skills/web/zap-scan-config/SKILL.md +444 -0
- package/skills/web/zap-scan-config/assets/.gitkeep +9 -0
- package/skills/web/zap-scan-config/assets/github_action.yml +207 -0
- package/skills/web/zap-scan-config/assets/gitlab_ci.yml +226 -0
- package/skills/web/zap-scan-config/assets/zap_automation.yaml +196 -0
- package/skills/web/zap-scan-config/assets/zap_context.xml +192 -0
- package/skills/web/zap-scan-config/references/EXAMPLE.md +40 -0
- package/skills/web/zap-scan-config/references/api_testing_guide.md +475 -0
- package/skills/web/zap-scan-config/references/authentication_guide.md +431 -0
- package/skills/web/zap-scan-config/references/false_positive_handling.md +427 -0
- package/skills/web/zap-scan-config/references/owasp_mapping.md +255 -0
- package/src/lrr/aggregator.ts +80 -0
- package/src/orchestrator/hooks/context-header.ts +95 -0
- package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
- package/src/orchestrator/hooks/token-accounting.ts +101 -0
- package/src/orchestrator/mcp/cycle-counter.ts +129 -0
- package/src/orchestrator/mcp/scribe.ts +283 -0
- package/src/orchestrator/mcp/state-save.ts +149 -0
- package/src/orchestrator/mcp/write-lease.ts +167 -0
- package/src/orchestrator/phase4-shared-context.ts +41 -0
- package/src/orchestrator/schemas/backward-edge.ts +46 -0
- package/agents/agentic-identity-trust.md +0 -121
- package/agents/data-consolidation-agent.md +0 -39
- package/agents/design-image-prompt-engineer.md +0 -105
- package/agents/design-visual-storyteller.md +0 -147
- package/agents/design-whimsy-injector.md +0 -89
- package/agents/engineering-autonomous-optimization-architect.md +0 -105
- package/agents/market-intel.md +0 -35
- package/agents/marketing-instagram-curator.md +0 -111
- package/agents/marketing-reddit-community-builder.md +0 -121
- package/agents/marketing-social-media-strategist.md +0 -74
- package/agents/marketing-tiktok-strategist.md +0 -123
- package/agents/marketing-twitter-engager.md +0 -124
- package/agents/marketing-wechat-official-account.md +0 -143
- package/agents/marketing-xiaohongshu-specialist.md +0 -136
- package/agents/marketing-zhihu-strategist.md +0 -160
- package/agents/product-behavioral-nudge-engine.md +0 -78
- package/agents/project-management-experiment-tracker.md +0 -102
- package/agents/report-distribution-agent.md +0 -43
- package/agents/risk-analysis.md +0 -45
- package/agents/sales-data-extraction-agent.md +0 -46
- package/agents/specialized-cultural-intelligence-strategist.md +0 -65
- package/agents/specialized-developer-advocate.md +0 -146
- package/agents/support-analytics-reporter.md +0 -133
- package/agents/support-executive-summary-generator.md +0 -64
- package/agents/support-finance-tracker.md +0 -145
- package/agents/support-legal-compliance-checker.md +0 -129
- package/agents/support-support-responder.md +0 -91
- package/agents/testing-accessibility-auditor.md +0 -110
- package/agents/testing-test-results-analyzer.md +0 -97
- package/agents/testing-tool-evaluator.md +0 -76
- package/agents/testing-workflow-optimizer.md +0 -99
- package/agents/user-research.md +0 -40
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Parallelization and Isolation
|
|
2
|
+
|
|
3
|
+
## When to use this reference
|
|
4
|
+
|
|
5
|
+
Use this file when tests are flaky in CI, have hidden ordering dependencies, or need to scale execution speed safely.
|
|
6
|
+
|
|
7
|
+
## Default execution model
|
|
8
|
+
|
|
9
|
+
- Swift Testing runs test functions in parallel by default.
|
|
10
|
+
- Execution order is randomized to expose hidden test dependencies.
|
|
11
|
+
- Parallelization applies to synchronous and asynchronous tests.
|
|
12
|
+
|
|
13
|
+
## Example: hidden dependency exposed by parallel execution
|
|
14
|
+
|
|
15
|
+
```swift
|
|
16
|
+
import Testing
|
|
17
|
+
|
|
18
|
+
enum SharedStore {
|
|
19
|
+
static var counter = 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Test func incrementsCounter() {
|
|
23
|
+
SharedStore.counter += 1
|
|
24
|
+
#expect(SharedStore.counter >= 1)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Test func expectsFreshCounter() {
|
|
28
|
+
// Flaky if tests run in parallel or random order.
|
|
29
|
+
#expect(SharedStore.counter == 0)
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Why this matters
|
|
34
|
+
|
|
35
|
+
- Faster CI feedback and shorter local iteration loops.
|
|
36
|
+
- Better detection of shared-state coupling and flaky behavior.
|
|
37
|
+
- More realistic stress on concurrency-sensitive code paths.
|
|
38
|
+
|
|
39
|
+
## Isolation strategy first
|
|
40
|
+
|
|
41
|
+
- Make tests independent by default.
|
|
42
|
+
- Avoid shared mutable globals and singleton mutation across tests.
|
|
43
|
+
- Isolate state per test invocation (fresh suite instance helps).
|
|
44
|
+
- Prefer deterministic test data setup over implicit ordering assumptions.
|
|
45
|
+
|
|
46
|
+
### Better pattern: isolate per test
|
|
47
|
+
|
|
48
|
+
```swift
|
|
49
|
+
import Testing
|
|
50
|
+
|
|
51
|
+
struct CounterStore {
|
|
52
|
+
var counter = 0
|
|
53
|
+
mutating func increment() { counter += 1 }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Test func isolatedCounter() {
|
|
57
|
+
var store = CounterStore()
|
|
58
|
+
store.increment()
|
|
59
|
+
#expect(store.counter == 1)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## `.serialized` as a targeted tool
|
|
64
|
+
|
|
65
|
+
- Apply `.serialized` to suites when tests must run one-at-a-time.
|
|
66
|
+
- Use it as a transitional safety measure during migration from serial XCTest suites.
|
|
67
|
+
- Refactor toward parallel-safe tests before normalizing serialization everywhere.
|
|
68
|
+
- Serialized suites can still run alongside unrelated suites in parallel.
|
|
69
|
+
|
|
70
|
+
### Transitional serialization example
|
|
71
|
+
|
|
72
|
+
```swift
|
|
73
|
+
import Testing
|
|
74
|
+
|
|
75
|
+
@Suite(.serialized)
|
|
76
|
+
struct LegacyDatabaseTests {
|
|
77
|
+
@Test func migrationStepA() { #expect(true) }
|
|
78
|
+
@Test func migrationStepB() { #expect(true) }
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Shared resource scenarios
|
|
83
|
+
|
|
84
|
+
- If tests hit a shared DB/file/service, choose one:
|
|
85
|
+
- isolate backing state per test
|
|
86
|
+
- use in-memory substitutes
|
|
87
|
+
- create separate serial test plan for integration path
|
|
88
|
+
- Prefer architecture that supports both fast in-memory tests and selective real integration tests.
|
|
89
|
+
|
|
90
|
+
## Do / Don't
|
|
91
|
+
|
|
92
|
+
- Do fix shared-state coupling before adding broad serialization.
|
|
93
|
+
- Do use in-memory fakes for the fast path.
|
|
94
|
+
- Don't rely on execution order.
|
|
95
|
+
- Don't mutate singletons across tests without reset/isolation.
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Parameterized Testing
|
|
2
|
+
|
|
3
|
+
## When to use this reference
|
|
4
|
+
|
|
5
|
+
Use this file when you have repeated tests with identical logic and only input changes.
|
|
6
|
+
|
|
7
|
+
## When to parameterize
|
|
8
|
+
|
|
9
|
+
- Use one parameterized test when behavior is identical and only input changes.
|
|
10
|
+
- Replace copy-pasted tests and in-test `for` loops with `@Test(arguments: ...)`.
|
|
11
|
+
- Keep one responsibility per parameterized test to preserve clarity.
|
|
12
|
+
|
|
13
|
+
### Before -> after
|
|
14
|
+
|
|
15
|
+
```swift
|
|
16
|
+
// Before: multiple near-duplicate tests.
|
|
17
|
+
// @Test func freeFeatureA() { ... }
|
|
18
|
+
// @Test func freeFeatureB() { ... }
|
|
19
|
+
|
|
20
|
+
import Testing
|
|
21
|
+
|
|
22
|
+
enum Feature: CaseIterable {
|
|
23
|
+
case recording, darkMode, networkMonitor
|
|
24
|
+
var isPremium: Bool { self == .networkMonitor }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Test("Free features are not premium", arguments: [Feature.recording, .darkMode])
|
|
28
|
+
func freeFeatures(_ feature: Feature) {
|
|
29
|
+
#expect(feature.isPremium == false)
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Single input collection
|
|
34
|
+
|
|
35
|
+
- Pass any sendable collection (arrays, ranges, dictionaries, etc.) as arguments.
|
|
36
|
+
- Each argument becomes its own independent test case with separate diagnostics.
|
|
37
|
+
- Individual failing arguments can be rerun without rerunning all inputs.
|
|
38
|
+
|
|
39
|
+
### Range-based arguments example
|
|
40
|
+
|
|
41
|
+
```swift
|
|
42
|
+
import Testing
|
|
43
|
+
|
|
44
|
+
func isValidAge(_ value: Int) -> Bool { (18...120).contains(value) }
|
|
45
|
+
|
|
46
|
+
@Test(arguments: 18...21)
|
|
47
|
+
func validAges(_ age: Int) {
|
|
48
|
+
#expect(isValidAge(age))
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Multiple inputs
|
|
53
|
+
|
|
54
|
+
- Swift Testing supports up to two argument collections directly.
|
|
55
|
+
- Two collections generate all combinations (cartesian product).
|
|
56
|
+
- Control explosion by:
|
|
57
|
+
- reducing argument sets
|
|
58
|
+
- splitting tests by concern
|
|
59
|
+
- pairing related values via `zip(...)`
|
|
60
|
+
|
|
61
|
+
### Cartesian product example
|
|
62
|
+
|
|
63
|
+
```swift
|
|
64
|
+
import Testing
|
|
65
|
+
|
|
66
|
+
enum Region { case eu, us }
|
|
67
|
+
enum Plan { case free, pro }
|
|
68
|
+
|
|
69
|
+
func canUseVATInvoice(region: Region, plan: Plan) -> Bool {
|
|
70
|
+
region == .eu && plan == .pro
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Test(arguments: [Region.eu, .us], [Plan.free, .pro])
|
|
74
|
+
func vatInvoiceAccess(region: Region, plan: Plan) {
|
|
75
|
+
let allowed = canUseVATInvoice(region: region, plan: plan)
|
|
76
|
+
#expect((region == .eu && plan == .pro) == allowed)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## `zip` for paired scenarios
|
|
81
|
+
|
|
82
|
+
- Use `zip` when input A must pair with a corresponding input B.
|
|
83
|
+
- Prefer `zip` over full combinations when you need aligned tuples only.
|
|
84
|
+
- Keep tuples readable and intentional.
|
|
85
|
+
|
|
86
|
+
### `zip` example
|
|
87
|
+
|
|
88
|
+
```swift
|
|
89
|
+
import Testing
|
|
90
|
+
|
|
91
|
+
enum Tier { case basic, premium }
|
|
92
|
+
func freeTries(for tier: Tier) -> Int { tier == .basic ? 3 : 10 }
|
|
93
|
+
|
|
94
|
+
@Test(arguments: zip([Tier.basic, .premium], [3, 10]))
|
|
95
|
+
func freeTryLimits(_ tier: Tier, expected: Int) {
|
|
96
|
+
#expect(freeTries(for: tier) == expected)
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `zip` pitfalls to avoid
|
|
101
|
+
|
|
102
|
+
**Silent truncation**: `zip` stops at the shorter collection. If the two arrays differ in length, the extra elements are silently dropped — no compiler error, no test failure, just missing coverage.
|
|
103
|
+
|
|
104
|
+
```swift
|
|
105
|
+
// ❌ Silent gap: the fifth input is never tested
|
|
106
|
+
@Test(arguments: zip(
|
|
107
|
+
[Status.active, .inactive, .pending, .banned, .suspended],
|
|
108
|
+
["Active", "Inactive", "Pending", "Banned"] // one short
|
|
109
|
+
))
|
|
110
|
+
func statusLabel(_ status: Status, expected: String) {
|
|
111
|
+
#expect(label(for: status) == expected)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Case-order fragility with `CaseIterable`**: pairing two `allCases` arrays with `zip` breaks silently if enum cases are ever reordered (e.g., by alphabetizing).
|
|
116
|
+
|
|
117
|
+
```swift
|
|
118
|
+
// ❌ Fragile: reordering either enum misaligns all pairs
|
|
119
|
+
enum Ingredient: CaseIterable { case rice, potato, egg }
|
|
120
|
+
enum Dish: CaseIterable { case onigiri, fries, omelette }
|
|
121
|
+
|
|
122
|
+
@Test(arguments: zip(Ingredient.allCases, Dish.allCases))
|
|
123
|
+
func cook(_ ingredient: Ingredient, into dish: Dish) {
|
|
124
|
+
#expect(cook(ingredient) == dish)
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Prefer explicit array literals or one of the alternatives below.
|
|
129
|
+
|
|
130
|
+
## Paired input alternatives
|
|
131
|
+
|
|
132
|
+
When inputs and expected outputs must be paired, prefer these over `zip` to avoid the silent-truncation and case-ordering problems.
|
|
133
|
+
|
|
134
|
+
### Array of tuples (recommended)
|
|
135
|
+
|
|
136
|
+
Pairs are co-located and impossible to misalign. Adding a new case forces a matching output to be written at the same time.
|
|
137
|
+
|
|
138
|
+
```swift
|
|
139
|
+
import Testing
|
|
140
|
+
|
|
141
|
+
@Test(arguments: [
|
|
142
|
+
(Ingredient.rice, Dish.onigiri),
|
|
143
|
+
(.potato, .fries),
|
|
144
|
+
(.egg, .omelette)
|
|
145
|
+
])
|
|
146
|
+
func cook(_ ingredient: Ingredient, into dish: Dish) {
|
|
147
|
+
#expect(cook(ingredient) == dish)
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Dictionary arguments
|
|
152
|
+
|
|
153
|
+
Expresses a clear mapping; each entry is self-documenting. Requires `Hashable` keys.
|
|
154
|
+
|
|
155
|
+
```swift
|
|
156
|
+
import Testing
|
|
157
|
+
|
|
158
|
+
@Test(arguments: [
|
|
159
|
+
Ingredient.rice: Dish.onigiri,
|
|
160
|
+
.potato: .fries,
|
|
161
|
+
.egg: .omelette
|
|
162
|
+
])
|
|
163
|
+
func cook(_ ingredient: Ingredient, into dish: Dish) {
|
|
164
|
+
#expect(cook(ingredient) == dish)
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Fixed-size `zip` with `InlineArray` (Swift 6.2+)
|
|
169
|
+
|
|
170
|
+
A custom `zip` overload for `InlineArray` enforces equal-length arrays at compile time via a generic length parameter. This is not part of the standard library — you must define the helper yourself.
|
|
171
|
+
|
|
172
|
+
```swift
|
|
173
|
+
import Testing
|
|
174
|
+
|
|
175
|
+
// Custom helper: `zip` for two `InlineArray` values of the same length.
|
|
176
|
+
func zip<let N: Int, A, B>(
|
|
177
|
+
_ a: InlineArray<N, A>,
|
|
178
|
+
_ b: InlineArray<N, B>
|
|
179
|
+
) -> Zip2Sequence<[A], [B]> {
|
|
180
|
+
zip(Array(a), Array(b))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ✅ Compile error if lengths differ — enforced at compile time
|
|
184
|
+
@Test(arguments: zip(
|
|
185
|
+
InlineArray<2, Ingredient>(.rice, .potato),
|
|
186
|
+
InlineArray<2, Dish>(.onigiri, .curry)
|
|
187
|
+
))
|
|
188
|
+
func cook(_ ingredient: Ingredient, into dish: Dish) {
|
|
189
|
+
#expect(cook(ingredient) == dish)
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Naming and output quality
|
|
194
|
+
|
|
195
|
+
- Use meaningful parameter labels and display names.
|
|
196
|
+
- Ensure argument types are readable in output; provide custom test description if noisy.
|
|
197
|
+
- Keep argument lists easy to scan (multi-line formatting is recommended).
|
|
198
|
+
|
|
199
|
+
## When `CaseIterable.allCases` is appropriate
|
|
200
|
+
|
|
201
|
+
Using `allCases` as arguments is a valid pattern for **property-based tests** — tests that verify a universal property holds for every member of a type. The key distinction: the expected result is derived from the *property being tested*, not from a hard-coded mapping.
|
|
202
|
+
|
|
203
|
+
```swift
|
|
204
|
+
import Testing
|
|
205
|
+
|
|
206
|
+
// ✅ Valid: verifying a mathematical property holds for all orientations.
|
|
207
|
+
@Test(
|
|
208
|
+
"Rotating clockwise four times returns to the original orientation",
|
|
209
|
+
arguments: Orientation.allCases
|
|
210
|
+
)
|
|
211
|
+
func fullRotation(orientation: Orientation) {
|
|
212
|
+
#expect(
|
|
213
|
+
orientation
|
|
214
|
+
.rotated(.clockwise)
|
|
215
|
+
.rotated(.clockwise)
|
|
216
|
+
.rotated(.clockwise)
|
|
217
|
+
.rotated(.clockwise)
|
|
218
|
+
== orientation
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Avoid `allCases` when you need concrete, case-specific expected values — use explicit arrays or tuples instead.
|
|
224
|
+
|
|
225
|
+
## Common pitfalls
|
|
226
|
+
|
|
227
|
+
- **Derived expected values masking bugs**: when the expected value is derived from the same input expression as the system under test, both sides shift together and bugs pass silently. Use concrete literals in `#expect` for case-specific expectations.
|
|
228
|
+
|
|
229
|
+
```swift
|
|
230
|
+
// ❌ Masking: if format(day) returns "monday" instead of "Monday",
|
|
231
|
+
// this test still passes because rawValue has the same casing bug.
|
|
232
|
+
@Test(arguments: Day.allCases)
|
|
233
|
+
func dayLabel(day: Day) {
|
|
234
|
+
#expect(format(day) == day.rawValue)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ✅ Concrete: each expectation is an independent data point.
|
|
238
|
+
@Test(arguments: [
|
|
239
|
+
(Day.monday, "Monday"),
|
|
240
|
+
(.friday, "Friday")
|
|
241
|
+
])
|
|
242
|
+
func dayLabel(day: Day, expected: String) {
|
|
243
|
+
#expect(format(day) == expected)
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- **Control flow in test bodies**: `if`/`switch` inside a parameterized test body mirrors implementation logic. Tests that branch the same way as production code verify themselves rather than the behavior independently.
|
|
248
|
+
|
|
249
|
+
```swift
|
|
250
|
+
// ❌ Mirrors implementation — not independent verification.
|
|
251
|
+
@Test(arguments: Day.allCases)
|
|
252
|
+
func greeting(day: Day) {
|
|
253
|
+
if day == .friday {
|
|
254
|
+
#expect(greet(day) == "TGIF!")
|
|
255
|
+
} else {
|
|
256
|
+
#expect(greet(day) == "Hello, \(day)!")
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ✅ Separate the special case into its own test.
|
|
261
|
+
@Test func fridayGreeting() {
|
|
262
|
+
#expect(greet(.friday) == "TGIF!")
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@Test(arguments: [Day.monday, .tuesday, .wednesday, .thursday, .saturday, .sunday])
|
|
266
|
+
func standardGreeting(day: Day) {
|
|
267
|
+
#expect(greet(day) == "Hello, \(day)!")
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
- **Using in-test `for` loops instead of parameterized arguments** (worse diagnostics).
|
|
272
|
+
- **Passing huge argument sets that explode combinations** and slow CI.
|
|
273
|
+
- **Mixing multiple concerns into one parameterized function**.
|
|
274
|
+
- **Extracting argument arrays into separate properties or extensions**: this hides what the test covers and forces readers to jump between definitions. Keep arguments inline unless the list is genuinely reused across multiple test functions.
|
|
275
|
+
|
|
276
|
+
## Review checklist
|
|
277
|
+
|
|
278
|
+
- Repetitive tests are consolidated into one parameterized test.
|
|
279
|
+
- Arguments reflect domain vocabulary and produce readable failures.
|
|
280
|
+
- Paired inputs are modeled as arrays of tuples or dictionaries; use `zip` with equal-length explicit arrays only when the inputs must remain as separate collections.
|
|
281
|
+
- Paired inputs use tuples or dictionaries rather than `zip(allCases, allCases)`.
|
|
282
|
+
- `#expect` uses concrete literal expectations, not values derived from the input itself.
|
|
283
|
+
- No `if`/`switch` branching inside parameterized test bodies.
|
|
284
|
+
- `CaseIterable.allCases` is only used for property-based assertions, not example-based mappings.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Performance and Best Practices
|
|
2
|
+
|
|
3
|
+
## When to use this reference
|
|
4
|
+
|
|
5
|
+
Use this file when test runs are slow, flaky, or not scaling in CI, and when you need practical patterns for fast, deterministic Swift Testing suites.
|
|
6
|
+
|
|
7
|
+
## Core principles
|
|
8
|
+
|
|
9
|
+
- Prefer deterministic tests over timing-sensitive tests.
|
|
10
|
+
- Prefer synchronous verification when asynchronous waiting is not required.
|
|
11
|
+
- Keep tests independent so parallel execution remains safe and effective.
|
|
12
|
+
- Treat `.serialized` as a temporary compromise, not a default architecture.
|
|
13
|
+
|
|
14
|
+
## 1) Keep tests synchronous where possible
|
|
15
|
+
|
|
16
|
+
Synchronous tests generally run faster and are easier to reason about.
|
|
17
|
+
|
|
18
|
+
```swift
|
|
19
|
+
import Testing
|
|
20
|
+
|
|
21
|
+
struct PriceCalculator {
|
|
22
|
+
static func total(_ subtotal: Int, discount: Int) -> Int { subtotal - discount }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Test func totalCalculation() {
|
|
26
|
+
#expect(PriceCalculator.total(100, discount: 20) == 80)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Avoid introducing `async` or sleeps for purely synchronous logic.
|
|
31
|
+
|
|
32
|
+
```swift
|
|
33
|
+
// Avoid:
|
|
34
|
+
// @Test func totalCalculation() async {
|
|
35
|
+
// try await Task.sleep(nanoseconds: 100_000_000)
|
|
36
|
+
// #expect(...)
|
|
37
|
+
// }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 2) Avoid unnecessary main-actor isolation
|
|
41
|
+
|
|
42
|
+
`@MainActor` can reduce useful parallelization and should be used only when code truly needs main-thread isolation.
|
|
43
|
+
|
|
44
|
+
```swift
|
|
45
|
+
import Testing
|
|
46
|
+
|
|
47
|
+
// Good: non-UI logic stays non-main-actor.
|
|
48
|
+
@Test func parserIsStable() {
|
|
49
|
+
#expect("A,B,C".split(separator: ",").count == 3)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Use @MainActor only for UI/main-thread sensitive code.
|
|
53
|
+
@MainActor
|
|
54
|
+
@Test func viewModelMutation() {
|
|
55
|
+
#expect(true)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 3) Remove shared mutable state
|
|
60
|
+
|
|
61
|
+
Shared mutable state is a major source of flakiness and parallel failures.
|
|
62
|
+
|
|
63
|
+
```swift
|
|
64
|
+
import Testing
|
|
65
|
+
|
|
66
|
+
enum Globals {
|
|
67
|
+
static var token: String?
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Flaky pattern:
|
|
71
|
+
@Test func writeToken() {
|
|
72
|
+
Globals.token = "abc"
|
|
73
|
+
#expect(Globals.token == "abc")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Test func expectsNoToken() {
|
|
77
|
+
#expect(Globals.token == nil)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Better: create isolated state per test.
|
|
82
|
+
|
|
83
|
+
```swift
|
|
84
|
+
import Testing
|
|
85
|
+
|
|
86
|
+
struct SessionState {
|
|
87
|
+
var token: String?
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@Test func isolatedTokenState() {
|
|
91
|
+
var state = SessionState()
|
|
92
|
+
state.token = "abc"
|
|
93
|
+
#expect(state.token == "abc")
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 4) Prefer in-memory dependencies for the fast path
|
|
98
|
+
|
|
99
|
+
Use fakes/in-memory repositories for high-volume test runs; reserve real integration dependencies for dedicated plans.
|
|
100
|
+
|
|
101
|
+
```swift
|
|
102
|
+
import Testing
|
|
103
|
+
|
|
104
|
+
protocol CacheStore {
|
|
105
|
+
func put(key: String, value: String)
|
|
106
|
+
func get(key: String) -> String?
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
final class InMemoryCacheStore: CacheStore {
|
|
110
|
+
private var values: [String: String] = [:]
|
|
111
|
+
func put(key: String, value: String) { values[key] = value }
|
|
112
|
+
func get(key: String) -> String? { values[key] }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@Test func cacheRoundTrip() {
|
|
116
|
+
let cache = InMemoryCacheStore()
|
|
117
|
+
cache.put(key: "user", value: "42")
|
|
118
|
+
#expect(cache.get(key: "user") == "42")
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 5) Use parameterized tests to reduce overhead and improve diagnostics
|
|
123
|
+
|
|
124
|
+
```swift
|
|
125
|
+
import Testing
|
|
126
|
+
|
|
127
|
+
func isValidPort(_ value: Int) -> Bool { (1...65535).contains(value) }
|
|
128
|
+
|
|
129
|
+
@Test(arguments: [1, 80, 443, 65535])
|
|
130
|
+
func validPorts(_ port: Int) {
|
|
131
|
+
#expect(isValidPort(port))
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This reduces duplicated setup code and gives argument-level failure visibility.
|
|
136
|
+
|
|
137
|
+
## 6) Keep setup cheap and scoped
|
|
138
|
+
|
|
139
|
+
- Build expensive fixtures only when needed.
|
|
140
|
+
- Prefer per-suite immutable setup for shared readonly data.
|
|
141
|
+
- Avoid network/file-system setup in unit tests unless behavior depends on it.
|
|
142
|
+
|
|
143
|
+
```swift
|
|
144
|
+
import Testing
|
|
145
|
+
|
|
146
|
+
struct CurrencyTests {
|
|
147
|
+
let rates: [String: Double]
|
|
148
|
+
|
|
149
|
+
init() {
|
|
150
|
+
rates = ["USD": 1.0, "EUR": 0.92]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@Test func hasEURRate() {
|
|
154
|
+
#expect(rates["EUR"] != nil)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 7) Use `.serialized` narrowly
|
|
160
|
+
|
|
161
|
+
```swift
|
|
162
|
+
import Testing
|
|
163
|
+
|
|
164
|
+
@Suite(.serialized)
|
|
165
|
+
struct TemporarySerialDBTests {
|
|
166
|
+
@Test func migrationA() async throws { #expect(true) }
|
|
167
|
+
@Test func migrationB() async throws { #expect(true) }
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Add TODO context and remove once dependencies are isolated.
|
|
172
|
+
|
|
173
|
+
## 8) Flakiness reduction checklist
|
|
174
|
+
|
|
175
|
+
- No reliance on execution order.
|
|
176
|
+
- No shared mutable globals/singletons without reset.
|
|
177
|
+
- No arbitrary sleeps as synchronization.
|
|
178
|
+
- No hidden external dependencies in unit tests.
|
|
179
|
+
- Deterministic fixtures and stable clocks/random sources.
|
|
180
|
+
- Explicit known-issue wrappers for temporary failures.
|
|
181
|
+
|
|
182
|
+
## Quick do / don't
|
|
183
|
+
|
|
184
|
+
- Do optimize for determinism first, then speed.
|
|
185
|
+
- Do keep most tests parallel-safe and dependency-light.
|
|
186
|
+
- Don't treat test slowness as only a hardware problem.
|
|
187
|
+
- Don't move everything to `@MainActor` or `.serialized` to silence flakiness.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Traits and Tags
|
|
2
|
+
|
|
3
|
+
## When to use this reference
|
|
4
|
+
|
|
5
|
+
Use this file when controlling test execution behavior, linking bug context, and organizing large test suites for targeted runs and CI filtering.
|
|
6
|
+
|
|
7
|
+
## Trait categories
|
|
8
|
+
|
|
9
|
+
- **Informational**: display names, bug links, tags.
|
|
10
|
+
- **Conditional**: `.enabled(if:)`, `.disabled(...)`, availability attributes.
|
|
11
|
+
- **Behavioral**: `.timeLimit(...)`, `.serialized`.
|
|
12
|
+
|
|
13
|
+
## Basic trait examples
|
|
14
|
+
|
|
15
|
+
```swift
|
|
16
|
+
import Testing
|
|
17
|
+
|
|
18
|
+
@Test("Uploads complete quickly", .timeLimit(.seconds(10)))
|
|
19
|
+
func uploadWithinTimeLimit() async throws {
|
|
20
|
+
#expect(true)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Test(.disabled("Flaky on CI while investigating issue"), .bug("https://example.com/issues/12"))
|
|
24
|
+
func temporaryDisabledTest() {
|
|
25
|
+
#expect(true)
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Conditions and disabling
|
|
30
|
+
|
|
31
|
+
- Use `.enabled(if:)` or `.disabled(if:)` for runtime-evaluated environments.
|
|
32
|
+
- Use `.disabled("reason")` instead of commenting tests out.
|
|
33
|
+
- Include actionable reason text in disabled traits for CI/test reports.
|
|
34
|
+
- Add `.bug(...)` to link issue trackers and aid future cleanup.
|
|
35
|
+
|
|
36
|
+
### Runtime condition example
|
|
37
|
+
|
|
38
|
+
```swift
|
|
39
|
+
import Testing
|
|
40
|
+
|
|
41
|
+
enum Runtime {
|
|
42
|
+
static let isCI = ProcessInfo.processInfo.environment["CI"] == "true"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Test(.enabled(if: Runtime.isCI))
|
|
46
|
+
func ciOnlySmokeTest() {
|
|
47
|
+
#expect(true)
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Availability
|
|
52
|
+
|
|
53
|
+
- Use `@available` on tests when entire behavior is OS-gated.
|
|
54
|
+
- Prefer `@available` over inline runtime checks for clearer reporting semantics.
|
|
55
|
+
|
|
56
|
+
```swift
|
|
57
|
+
import Testing
|
|
58
|
+
|
|
59
|
+
@available(iOS 18, *)
|
|
60
|
+
@Test func modernPushPayload() {
|
|
61
|
+
#expect(true)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Tags
|
|
66
|
+
|
|
67
|
+
- Declare custom tags and apply to tests/suites for cross-suite grouping.
|
|
68
|
+
- Use tags for test-plan include/exclude, navigator filtering, and failure analytics.
|
|
69
|
+
- Treat tags as cross-cutting metadata, not a replacement for suite structure.
|
|
70
|
+
- Use meaningful domain labels (e.g. `networking`, `regression`, `spicy`) over vague terms.
|
|
71
|
+
|
|
72
|
+
### Defining and applying tags
|
|
73
|
+
|
|
74
|
+
```swift
|
|
75
|
+
import Testing
|
|
76
|
+
|
|
77
|
+
extension Tag {
|
|
78
|
+
@Tag static var networking: Self
|
|
79
|
+
@Tag static var regression: Self
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@Suite(.tags(.networking))
|
|
83
|
+
struct APITests {
|
|
84
|
+
@Test func fetchUser() async throws {
|
|
85
|
+
#expect(true)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
struct CheckoutTests {
|
|
90
|
+
@Test(.tags(.regression))
|
|
91
|
+
func orderTotal() {
|
|
92
|
+
#expect(3 * 3 == 9)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Inheritance and scope
|
|
98
|
+
|
|
99
|
+
- Traits and tags on suites cascade to contained tests.
|
|
100
|
+
- Apply at suite level when broadly true; apply per test when specific.
|
|
101
|
+
- Keep trait intent explicit to avoid accidental broad behavior changes.
|
|
102
|
+
|
|
103
|
+
## Do / Don't
|
|
104
|
+
|
|
105
|
+
- Do put shared tags at suite level for consistency.
|
|
106
|
+
- Do attach bug links for temporary disables or known failures.
|
|
107
|
+
- Don't use tags as a replacement for meaningful suite grouping.
|
|
108
|
+
- Don't overuse `.serialized` as a blanket reliability fix.
|
|
109
|
+
|
|
110
|
+
## Review checklist
|
|
111
|
+
|
|
112
|
+
- Every disabled test has a reason (and ideally a bug link).
|
|
113
|
+
- Tags reflect domain concerns and are reused consistently.
|
|
114
|
+
- Availability and condition traits are applied to the smallest correct scope.
|