# Test-driven, when it applies.

Write the test first. Watch it fail. Write the minimal code to pass. If you didn’t watch it fail, you don’t know it tests the right thing — tests written after code pass immediately, which proves nothing.

## When it applies

Bug fixes (a failing test reproduces the bug, the fix makes it pass), behaviour changes, and feature work with clear inputs and outputs. Refactoring of already-tested code, where the existing suite is the safety net.

Where it doesn’t — and isn’t forced: exploratory spikes, framework or config scaffolding, one-off scripts, and documentation-only changes. When uncertain, the default is to write the test — the 30 seconds to find out usually costs less than debugging later.

## Red · Green · Refactor

Red — one test, one behaviour, then watch it fail for the expected reason. Green — the simplest code that passes; no extra parameters “for the future.” Refactor — clean up only after green, with tests staying green throughout.

The `task` protocol’s implementation step expects this discipline; the [optimize](https://team.management/protocols/optimize.md) protocol’s frozen-paths hook physically prevents editing tests mid-experiment.

## Watch it fail

Running it before the code exists is the step people skip. It is also the step that does all the work. Three things can happen, and each one tells you something.

It passes. Then the behaviour already exists somewhere, and you did not write what you thought you wrote. Fix the assertion before you go further.

It errors out with a traceback. Then you have a typo or a bad import. An error is not a failure — it proves nothing about the behaviour you care about. Clear it and run again.

It fails with the message you predicted. Only this third case is evidence. Now you can write code, and you will know when you are done.

## The excuses

Four of them come up again and again, usually late in the day when the work is nearly finished. None of them survives contact with what happens next.

| The excuse                                  | What is actually true                                                                                         |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| “I’ll write it afterwards — that’s faster.” | Written afterwards, it goes green on the first run. Going green on the first run is not evidence of anything. |
| “I already checked every case by hand.”     | Ad-hoc checks are not repeatable. The next change breaks them silently.                                       |
| “This is too simple to need one.”           | Simple code breaks too, and writing it takes about thirty seconds.                                            |
| “I’ve already spent hours on this code.”    | Sunk cost. Unverified code is debt you pay later, with interest.                                              |

## When it gets hard

Difficulty here is information, not an obstacle. If it is hard to write, the design is usually too coupled — listen to that before you fight it. If you find yourself mocking everything in sight, what is missing is dependency injection: pass the collaborator in rather than standing in for it.

And if you simply don’t know how to begin, write the call you wish existed, then make it real.
