You have seen tests as a safety net you add after the code already works. There is a sharper move that flips the order: you write the test first, before the code exists, describing exactly what success looks like. Then the agent writes code until that test passes. This chapter shows you how to run that loop with an agent, and when the flip is worth it.
7.4.1Write the test before the code
Test-driven development (TDD) means writing the test before the thing it tests. You describe the behavior you want as a test that must pass, then write only enough code to make it pass. The test is not a check you bolt on at the end. It is the specification you build toward.
The order sounds backwards until you see what it buys. You cannot write a test for "checkout works" without first deciding what "works" means. Writing the test first forces that definition before a single line of the feature exists.
7.4.2Red, green, refactor
The cycle has a name, red-green-refactor, and three beats you repeat:
- Red: write one small failing test and run it. It fails because the code it needs does not exist yet, and that red proves the test really checks something.
- Green: write the least code that makes the test pass. Nothing extra, nothing clever, just green.
- Refactor: with the test passing, clean up the code. It stays green, so you know the cleanup broke nothing.
// 1. RED: write the test first, before the code exists.
test("splits a bill evenly", () => {
expect(splitBill(100, 4)).toBe(25);
});
$ npm test
FAIL splitBill is not defined
// 2. GREEN: the agent writes just enough to pass.
function splitBill(total, people) {
return total / people;
}
$ npm test
PASS splits a bill evenly
7.4.3Why it fits AI so well
Handing an agent a failing test is the most precise instruction you can give it. Most prompts describe what you want in words the agent can read loosely. A test is exact: this input must produce that output, and the machine runs it to check.
It also closes the agent's favorite escape hatch. An agent will cheerfully report a feature done. A red test that has to go green is a fact it cannot talk its way around, so you get a spec it codes toward and a finish line it cannot fake.
7.4.4When to use it, when to skip it
TDD shines when you can state success exactly before you build. It gets in the way when you are still discovering what you want.
| Write the test first | Skip it, cover it after |
|---|---|
| Tricky logic with a right answer (pricing, dates, permissions) | Exploratory UI you are still shaping |
| A bug: write the test that reproduces it, then fix to green | A quick prototype you may throw away |
| A rule you must never break again | A layout you judge by eye, not by assertion |
The dividing line is that one question: can you write down what "correct" means before the code exists? When you can, write the test first. When the honest answer is "I will know it when I see it," build first and cover it after, the way the safety-net chapter showed.
Act as a senior engineer practicing test-driven
development on my app. Write one small failing
test that says exactly what success looks like,
and run it so we both watch it fail. Then write
the least code that makes it pass, run it green,
and refactor without breaking it. Work one test
at a time, and never call a step done while its
test is still red.
The feature to build test-first:
Do this now: pick one piece of tricky logic in your app, write the failing test for it first, and let your agent turn it green before it writes anything else.