--- name: tdd-red-green-refactor description: Strict test-driven development — write the failing test first, make it pass minimally, then refactor. Prevents overbuilt code and pinpoints regressions. when_to_use: Before writing any behavior-adding code. Applies to Rust, TypeScript, Python, anywhere tests can run cheap. tags: [foundation, testing, tdd] --- # TDD: red → green → refactor ## The loop 1. **RED** — Write the test that fails because the behavior doesn't exist yet. Run it. Confirm it fails for the RIGHT reason (missing symbol, wrong output — not a syntax error). 2. **GREEN** — Write the simplest possible code that makes the test pass. Not the "correct" version — the SIMPLEST one. Hardcoded return value is legal. 3. **REFACTOR** — Now that you have a passing safety net, restructure. Extract, rename, tighten types. Every intermediate state must still be green. 4. **Commit the RED-to-GREEN pair as one commit.** The refactor is its own commit. ## Why this order - Writing the test first forces you to design the API from the caller's perspective. The API you wish existed usually beats the API you accidentally get. - Watching the test fail proves the test can fail — a test that has never failed is a test you don't trust. - Refactoring under a green bar means every step is safe. Refactoring in the dark means every step could silently break behavior. ## What counts as "a test" - Rust: `#[test]` unit test, `#[tokio::test]` async, or an integration test under `tests/`. Not a `println!`. - TypeScript: Vitest / Jest / Playwright. Storybook + a visual snapshot counts for component work. - Any language: it exits non-zero when the behavior is broken, without a human interpreting the output. ## Coverage discipline - Target: ≥90% line coverage on files you touched in this INT-XX item. Measured by `cargo llvm-cov` for Rust, `vitest --coverage` for TS. - Coverage regressions on changed files block merge — enforce via the mission's `commit_policy` (Slice 4). - 100% coverage is a smell — usually means testing implementation details. Aim for behavior coverage. ## Anti-patterns - Writing the impl first "because it's obvious" and adding tests after — you already lost the design feedback and the tests will inevitably shape to what the impl happens to do. - Testing multiple behaviors in one `#[test]` — a failure now hides what actually broke. - Snapshot-only test suites — snapshots catch NOTHING structural. Pair with at least one assertion per behavior.