Part II β The Shield Β· Lesson 4.6
Test-Driven Development
In one lineWrite the failing test first β it forces you to design the interface before the implementation.
Where you've seen itBuilding a usePagination hook. Writing the test first makes you decide what it returns before you decide how it works.
Diagram
THE CYCLE β minutes per lap, not hours
ββββββββββββββββββββ
β 1. RED β write the smallest failing test
β it must fail β β if it passes, it tests nothing
ββββββββββ¬ββββββββββ
βΌ
ββββββββββββββββββββ
β 2. GREEN β simplest code that passes
β ugly is fine β β hardcoding is allowed here
ββββββββββ¬ββββββββββ
βΌ
ββββββββββββββββββββ
β 3. REFACTOR β clean up, tests stay green
β no new behaviourβ β the safety net you just built
ββββββββββ¬ββββββββββ
β
ββββββββββββΊ next caseWHY "RED FIRST" IS NOT CEREMONY
test written AFTER code β tests what the code DOES
(bugs included, happily asserted)
test written BEFORE code β tests what the code SHOULD do
and proves the test can failWHAT TDD ACTUALLY IMPROVES
β interface design you're the first consumer of your own API
β small units hard-to-test code is usually badly factored
β refactoring nerve green suite = permission to change things
β not a substitute for integration or E2E coverage
β not free β expect it to feel slower for the first weekHow it works
- Write one failing test naming the behaviour you want. Run it and watch it fail.
- Write the minimum code to pass β hardcode if that's genuinely minimal.
- Add the next case; the hardcoding stops working and forces the real implementation.
- Refactor with the suite green. Behaviour must not change in this step.
- Repeat in short laps. If a lap takes 20 minutes, the step was too big.
Trade-offs
| TDD fits | TDD fights you |
|---|---|
| Pure logic, hooks, reducers, parsers | Exploratory UI and visual design |
| Bug fixes (reproduce first, then fix) | Spikes and throwaway prototypes |
| Well-understood requirements | Requirements you're still discovering |
The honest middle ground most teams land on: TDD for logic and bug fixes, test-after for UI composition, and always write the failing reproduction before fixing a reported bug β that one habit is non-negotiable and pays for itself immediately.
Interview angle
"Do you practise TDD?"
- For logic-heavy code and for every bug fix, yes β a bug without a failing test first has no proof it's fixed.
- For visual and exploratory UI work I build first and test the settled behaviour, because the interface is still moving.
- The durable benefit isn't coverage, it's that untestable code is usually badly designed code, and TDD surfaces that immediately.
Recap
- Red, green, refactor β and the red step is what proves the test works.
- TDD is an interface design tool that produces tests as a by-product.
- Reproduce every bug with a failing test before you fix it.