Core Cycle
RED → GREEN → REFACTOR → 반복
RED: Write a Failing Test
- Test only one behavior
- Clear name ("rejects empty email" ✅, "test1" ❌)
- Use real code (minimize mocks)
Verify: Confirm failure (mandatory! Do not skip)
npm test path/to/test.test.ts
- Does the test fail? (failure, not error)
- Is the failure message as expected?
- Does it fail because the feature is not implemented? (check for typos)
GREEN: Minimum Code
- The simplest code that passes the test
- Do not add features, do not refactor
- YAGNI (You Ain't Gonna Need It)
REFACTOR: Clean Up
- Remove duplication, improve names, extract helpers
- Tests remain GREEN
- Do not add behavior
Rules for Violations
테스트 전에 코드 작성했으면? → 삭제. 처음부터.
- "Let's keep it for reference" ❌
- "Let's apply it while writing tests" ❌
- "Let's not even look at it" ✅
When to Apply
Always:
- Implementing new features
- Bug fixes (write a bug-reproducing test first!)
- Behavior changes
Exceptions (master's judgment):
- One-off prototypes
- Configuration files
- Generated code
Common Rationalizations
| Excuse | Reality |
|---|---|
| "It's too simple to need tests" | Even simple code breaks. Testing takes 30 seconds |
| "I'll write tests later" | Later = passes immediately = proves nothing |
| "TDD is slow" | TDD is faster than debugging |
| "I tested it manually" | Manual = no record, cannot be rerun |
| "It's a waste to delete X hours of work" | Sunk cost. Unverified code is the real waste |
TDD for Bug Fixes
- Write a test that reproduces the bug
- Confirm RED (does the test catch the bug?)
- Write the fix
- Confirm GREEN
- Preserve it permanently as a regression test