From skill-issue
Defines testing philosophy emphasizing behavior over construction, fakes over mocks, predictable async, and database testing practices for Swift, Python, TypeScript. Use when writing, modifying, or auditing tests.
npx claudepluginhub crown-dev-studios/skill-issue --plugin skill-issueThis skill uses the workspace's default tool permissions.
This skill defines the testing principles for this codebase. Apply these when writing new tests, modifying existing tests, or reviewing test code.
anti-patterns.mdreferences/python/patterns.mdreferences/python/snippets/router-test.mdreferences/python/snippets/savepoint-fixture.mdreferences/python/snippets/service-test.mdreferences/swift-ios/patterns.mdreferences/swift-ios/snippets/actor-isolation-test.mdreferences/swift-ios/snippets/async-behavior-test.mdreferences/swift-ios/snippets/controlled-service.mdreferences/typescript/patterns.mdreferences/typescript/snippets/integration-test.mdreferences/typescript/snippets/unit-test.mdMandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
This skill defines the testing principles for this codebase. Apply these when writing new tests, modifying existing tests, or reviewing test code.
A test should prove the system does the right thing in response to a stimulus, not that it's wired up correctly.
Every test must exercise a decision the code makes. If the code under test doesn't make a decision in the scenario you're testing, the test has no value.
Never test that a property holds the value you just assigned. Never test that an initializer sets fields. Test what happens when the system acts on its state.
Valuable: "When the service rejects an unsupported sample rate, recording fails with a specific error."
Worthless: "The service has a sampleRate property set to 44100."
Test one representative from each user-facing error category — retryable, permanent, validation. If NetworkError has .timeout, .noConnection, .dnsFailure, pick one. They produce the same UX behavior. Add a variant test only when the behavior diverges (e.g., 401 triggers logout vs. 500 shows retry).
If you find yourself asserting mock.methodWasCalledWith(args), ask: is there an observable side effect I can check instead? Mocks test wiring. Fakes test behavior.
No dogma about one assertion per test. A test should be a coherent scenario — set up a situation, perform an action, verify the outcomes. Multiple assertions that validate different facets of the same behavior belong together. But don't test unrelated behaviors in a single test.
Never use Task.sleep or time-based delays in tests. Control the stimulus deterministically:
The principle: control the stimulus, don't observe the timing.
Test against the same database engine you run in production. No SQLite stand-ins for Postgres. The dialect differences will hide real bugs and surface fake ones.
Do not optimize for percentage coverage. Coverage tells you what code was executed, not whether it was meaningfully tested. A test that exercises a code path without verifying behavior inflates coverage and provides false confidence.
UI tests are the most flaky category of test. Do not write SwiftUI view tests or snapshot tests. Test ViewModels and services instead — they contain the decisions.
Test through the HTTP layer (e.g., TestClient, httpx.AsyncClient, or app instance). These verify the API contract: authentication, request validation, status codes, response shape.
Call the service directly. These verify business logic with real dependencies (database). Don't duplicate what router tests already cover.
No dependencies. Input in, output out. Test decision-making in isolation.