Test-Driven Development
Write the test first. Watch it fail. Write minimal code to pass.
The Iron Law
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
Any code written before its corresponding test must be deleted entirely - no exceptions for "reference" or "adapting" existing work.
Red-Green-Refactor Cycle
RED: Write Failing Test
- •Write ONE minimal failing test demonstrating desired behavior
- •Use clear naming that describes the behavior
- •Test real code, not mocks (mock only external dependencies)
- •Focus on ONE behavior per test
Verify RED (CRITICAL)
Run tests and confirm:
- •Test fails (not errors)
- •Failure indicates missing feature
- •Error message matches expectations
If test passes immediately → DELETE IT (it proves nothing)
GREEN: Make It Pass
- •Implement the simplest code that passes the test
- •Avoid over-engineering
- •Don't add features not requested
- •Keep scope narrow
Verify GREEN
- •All tests pass
- •No other tests broke
REFACTOR: Clean Up
- •Clean up while ALL tests remain green
- •Remove duplication (DRY)
- •Improve naming
- •Extract helpers if needed
Why Tests-First Matters
Tests written after code pass immediately, proving nothing about their validity. Tests-first:
- •Force discovery of edge cases before implementation
- •Provide systematic verification impossible with manual testing
- •Document expected behavior
Common Rationalizations (ALL REJECTED)
| Excuse | Why It's Wrong |
|---|---|
| "Too simple to test" | Simple code still needs verification |
| "I'll test after" | Tests-after pass immediately, proving nothing |
| "Already manually tested" | Manual testing isn't repeatable or documented |
| "Deleting hours of work is wasteful" | Sunk cost fallacy - untested code is liability |
When to Use TDD
Always: New features, bug fixes, refactoring, behavior changes
Exceptions only: Throwaway prototypes, generated code, config files (with permission)
Red Flags Requiring Restart
- •Code written before test
- •Test passes immediately
- •Can't explain why test should fail
- •Rationalizing "just this once"
→ DELETE the code and recommence with failing test
When 3+ Test Fixes Fail
STOP. This signals an architectural problem:
- •Return to investigation phase
- •Question whether the underlying pattern is sound
- •Discuss with user before attempting more fixes