skills/swift-tdd/SKILL.md
Use when implementing any Swift or SwiftUI feature or bugfix, before writing implementation code
npx skillsauth add andrewdmontgomery/powerswift swift-tddInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The fundamental approach is: Write the test first. Watch it fail. Write minimal code to pass.
Core principle: "If you didn't watch the test fail, you don't know if it tests the right thing."
This skill combines Test-Driven Development discipline with Swift Testing, SwiftUI, and Swift Concurrency best practices.
Apply TDD consistently for:
Exceptions require explicit human approval and typically only apply to throwaway prototypes, generated code, asset catalogs, or configuration plists.
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.
Code written before tests must be deleted completely and reimplemented through TDD, without keeping it as reference material.
RED: Write one minimal failing test demonstrating required behavior
GREEN: Implement the simplest Swift code that passes the test
REFACTOR: Clean up code while keeping all tests green
@Observable classes)@MainActor and call them from @MainActor test contexts.@MainActor
@Suite("ProfileViewModel")
struct ProfileViewModelTests {
@Test("loading sets user name")
func loadingSetsUserName() async throws {
let fake = FakeUserService(stub: User(name: "Ada"))
let vm = ProfileViewModel(service: fake)
await vm.load()
#expect(vm.userName == "Ada")
}
}
#require to unwrap optionals when subsequent assertions depend on them.async and await all async calls — never spin or sleep.withCheckedContinuation or AsyncStream rather than XCTestExpectation.confirmation() for callback-based event verification.SwiftUI body should not be unit-tested directly. Instead:
@Observable view models and test the model.XCUIApplication) only for end-to-end critical paths.// GOOD — test the model that drives the view
@Test("submit disables when title is empty")
func submitDisabledWhenTitleEmpty() {
let vm = NewPostViewModel()
vm.title = ""
#expect(vm.isSubmitDisabled == true)
}
// AVOID — testing SwiftUI rendering or view hierarchy directly in unit tests
Use real code unless a boundary forces isolation:
| Boundary | Strategy |
|----------|----------|
| Network | Protocol + in-memory fake |
| Database | In-memory repository |
| System clock | Injected Clock / TimeProvider |
| File system | Temp directory per test |
| @Observable dependencies | Fake conforming to same protocol |
Never mock @Observable view models themselves — test them directly.
Before marking any task complete:
swift test or Xcode test navigator green)await, not sleeps or expectationsbody is notSee testing-anti-patterns.md for Swift-specific testing anti-patterns and how to fix them.
This skill works in conjunction with:
development
Use this skill when brainstorming, designing, or planning any Swift feature. This is the right skill whenever the user describes a feature they want to build, asks "how should I implement X", wants to think through a design, or starts with something like "I want to add..." or "let's plan...". Use it even if they don't explicitly say "brainstorm" — if there's a feature to figure out, start here before touching any code.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.