TDD as a Feedback Loop
Red, green, refactor is less about tests than about tight feedback — and in the age of coding agents, a failing test is the clearest instruction you can give.
On this page
When I first wrote about test-driven development I described it as a process: think, red, green, refactor, repeat. That’s still right. What I understand better now is why it works: TDD is a way of keeping the feedback loop between intent and code as short as possible.
The loop
Think first. Break the problem down before touching the keyboard. Sketch it, list the requirements, find the edge cases. A lot of problems — and a lot of stakeholder misunderstandings — surface here, before any code exists.
Red. Write one test for one requirement and watch it fail. If the test is hard to write, that’s a signal: the requirement is probably too big, or the design is fighting you. Split it.
Green. Write the simplest code that passes. Not the clever version, not the general version. If you find yourself writing beyond what the test asks for, the test doesn’t fully describe the requirement — go back and write the next one.
Refactor. Now, and only now, tidy up: names, duplication, structure. The tests are your safety net; the behaviour doesn’t change. New behaviour means a new red test first.
Repeat until the requirement is done.
What I’d add after a few more years
Test behaviour, not implementation. The tests that survive refactors are the ones that describe what a user or caller can observe. In UI work that means rendering components and interacting with them the way a person would — by role and label, not by internal state. Tests coupled to implementation details make refactoring harder, which defeats the point.
Mock at the boundary. Stubbing fetch in every test bakes assumptions into each one. Intercepting requests at the
network layer (I use MSW (Mock Service Worker)) keeps the real data layer in play and lets the same scenarios drive
tests, Storybook and local development.
Pick the right size of test for the question. A unit test answers “is this logic right?” quickly. A component test answers “does this behave right for a user?”. An end-to-end test answers “does the whole journey work?”. TDD works at all three levels; the red–green rhythm is the same, the loop is just longer as you go up.
It’s a design tool. Code written test-first tends to have smaller units, clearer inputs and outputs, and fewer hidden dependencies, because hard-to-test code is painful to write that way.
TDD and coding agents
The biggest change since I first wrote about this is who writes the green step. With a coding agent, the loop becomes:
- You (or the agent, with your review) write a failing test that pins down the behaviour.
- The agent writes code until it passes, running the tests itself.
- You review the diff and the refactor.
A failing test is the most precise instruction you can give an agent: unambiguous, checkable, and it tells the agent when to stop. Type checks, linters and test suites become feedback sensors that let the agent correct itself before a human looks — the same short loop TDD was always about, run by something faster than me.
Two cautions. Agents will happily write tests that assert very little, so review the tests harder than the code. And an agent that’s allowed to edit tests to make them pass has turned your safety net into decoration — make test changes an explicit, reviewed step.
Where it’s less useful
Exploratory spikes, throwaway prototypes and highly visual work often go faster without test-first. I spike to learn, then delete the spike and test-drive the real thing. TDD is a tool for confidence, not a ritual.
Takeaways
- TDD is about shortening feedback, not about having tests.
- One requirement per test; simplest code to pass; refactor only on green.
- Test behaviour at the boundaries the user or caller can see.
- With agents, a failing test is the best spec you can write — and the tests deserve the hardest review.
Related: SAID: Train for the Production You Actually Run on making tests realistic enough to matter.
Originally written in 2020 → Test Driven Development - Intro
- #tdd
- #testing
- #test-driven-development
- #coding-agents
- #feedback-loops
- #refactoring
↩ Linked from (1)
- Shift Left TestingGrowing
…React. The testing layers themselves are in React Testing Strategy, and the feedback-loop view of testing in TDD as a Feedback Loop.
↪ Links to (2)
Related by topic
- Growingcase study
Building a Low-Code BPMN Workflow Platform
Frontend craft - Seed
Convex
Frontend craft - Evergreen
Git Worktrees: A Desk per Branch
Frontend craft - Growingmetaphor
Golden Paths and the Recommended Routine
Calisthenics Lab