--- name: "test-driven-development" description: "Write the failing test before the implementation, for every feature or bugfix - red, green, refactor. Use before writing any implementation code, and when fixing a bug (reproduce it as a failing test first). Covers what makes a good test, why the order matters, the rationalizations that mean you are skipping it, and a verification checklist before marking work complete. Triggers: add a feature, fix this bug, implement X, write tests, TDD." --- 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. **The Iron Law: NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.** Wrote code before the test? Delete it — completely, don't keep it "as reference" — and start over from tests. Always use for: new features, bug fixes, refactoring, behavior changes. Exceptions (ask the user first): throwaway prototypes, generated code, configuration files. ## Red-Green-Refactor Cycle **RED — Write a failing test.** One minimal test showing what should happen. One behavior, clear name, real code (avoid mocks unless unavoidable). **Verify RED — watch it fail (mandatory, never skip).** Run just that test. Confirm: it fails (not errors), the failure message is what you'd expect, and it fails because the feature is missing — not because of a typo. If it passes, you're testing existing behavior — fix the test. If it errors, fix the error and re-run until it fails correctly. **GREEN — write the minimal code to pass.** Don't add extra features, options, or "improvements" beyond what the test requires (YAGNI). **Verify GREEN — watch it pass (mandatory).** Run the test — and the full suite. Confirm it passes, no other tests broke, and output is clean (no errors/warnings). If it fails, fix the code, not the test. **REFACTOR — clean up while green.** Remove duplication, improve names, extract helpers. Don't add new behavior. Keep tests green throughout. **Repeat** for the next behavior. ## Good Tests Minimal (one thing — "and" in the name means split it), clear (name describes behavior, not "test1"), and shows intent (demonstrates the desired API). ## Why Order Matters Tests written after code pass immediately — which proves nothing (might test the wrong thing, might test implementation not behavior, might miss edge cases you forgot). Test-first forces you to watch it fail, proving it actually tests something. Manual testing is ad-hoc — no record, can't re-run, easy to forget cases under pressure. ## Common Rationalizations (all mean: stop, do TDD properly) "Too simple to test" / "I'll test after" / "Already manually tested" / "Deleting X hours of work is wasteful" (sunk cost — keeping unverified code is technical debt) / "Keep as reference, write tests first" (you'll adapt it — that's testing after) / "Need to explore first" (fine — throw away exploration, start clean with TDD) / "Test is hard to write = design is unclear, but I'll push through anyway" (listen to the test) / "TDD will slow me down" (it's faster than debugging after). ## Verification Checklist (before marking work complete) - Every new function/method has a test - You watched each test fail before implementing, for the expected reason - Wrote minimal code to pass each test - All tests pass, output pristine - Tests use real code (mocks only if unavoidable) - Edge cases and errors covered Can't check all boxes? You skipped TDD — start over. ## Debugging Integration Bug found? Write a failing test reproducing it first, then follow the Red-Green-Refactor cycle. The test proves the fix and prevents regression. Never fix bugs without a test. ## Final Rule Production code → a test exists and failed first. Otherwise, it's not TDD. No exceptions without explicit user permission.