Philosophy
Tests verify behavior through public interfaces, not implementation details. Good tests read like a spec and survive refactors; bad tests mock internals and break without a behavior change. See tests.md and mocking.md.
Anti-Pattern: Horizontal Slices
DO NOT write all tests first, then all implementation ("horizontal slicing") -- it produces tests that check imagined shape, not real behavior. Correct approach: vertical slices via tracer bullets -- one test, one implementation, repeat.
WRONG (horizontal):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
RIGHT (vertical): RED→GREEN: test1→impl1 RED→GREEN: test2→impl2 RED→GREEN: test3→impl3 ...
## Workflow
### 1. Planning
- [ ] Confirm interface changes and which behaviors to test (prioritize) with the user
- [ ] Identify [deep modules](deep-modules.md) (small interface, deep implementation)
- [ ] Design for [testability](interface-design.md)
- [ ] List behaviors to test, not implementation steps; get user approval
- [ ] Focus on critical paths and complex logic -- you can't test everything
### 2. RED-GREEN Loop
Start with a tracer bullet -- one test proving the path end-to-end -- then repeat per behavior:
RED: Write test → fails GREEN: Minimal code to pass → passes
One test at a time; only enough code to pass it; don't anticipate future tests.
### 3. Refactor
After all tests pass, apply [refactor candidates](refactoring.md): extract duplication, deepen modules, apply SOLID where natural, run tests after each step. **Never refactor while RED.**
## Checklist Per Cycle
[ ] Test describes behavior, not implementation [ ] Test uses public interface only [ ] Test would survive internal refactor [ ] Code is minimal for this test [ ] No speculative features added