Back to blog

When TDD bites you in the ass

Blind TDD and verification can leave agents maintaining tests instead of making useful changes, so the workflow needs checking too.


Sometimes I hand an agent a small task, expect it to finish in seconds, and come back to find it took half an hour. What the hell happened?

One problem I’ve run into is tests that no longer earn their place. They stay in the repository, and agents spend time fixing them. If you aren’t reading every change, you might miss the buildup. You notice it another way. Runs take longer. The pipeline gets slower. A small change stops feeling small.

I haven’t measured how much of those long runs came from tests. But it has made me question the instructions I give agents. “Always do TDD” and “verify everything” sound responsible. Applied without judgment, they can also create work that doesn’t help me ship a better result.

A shuttered shop pinned with old green checks while a small robot loops red and green scraps back onto the door.

The tests need maintenance too

Looking back through my agent threads, one example was an archive check that still expected an old protocol version after the current contract had changed. The worker reported that mismatch and stopped. Delivery needed a fixture correction before verification could continue.

That doesn’t mean the test was always useless. It doesn’t tell us whether TDD produced it. It means its assertion had outlived the decision it was checking. The agent was right to flag the mismatch rather than change the product to satisfy it.

This is the bit a blanket testing rule misses. Adding a test creates something else to maintain. When behavior changes, someone needs to decide whether the old assertion still belongs. Otherwise, the next agent gets a failure and another repair job.

Tests can also freeze details that never needed protecting. If a helper moves but the public behavior stays the same, a test of the helper’s internal calls may create work without catching a product defect. That is different from a regression test that stops us charging someone twice.

The cost isn’t just test execution. Local test runs don’t consume model tokens by themselves. Sending failures and diffs back to the model, asking it to diagnose them, and repeating the edits does. A check can be cheap to run and expensive to keep repairing.

TDD still has a job

Another thread showed the useful side. A dependency scanner mistook test names and ordinary methods for imports. The recorded run added focused regression tests, saw them fail, corrected the scanner, and saw them pass.

That is a good reason to write the test first. There was a specific defect and a clear expected result. The failing test showed it could detect the problem before the fix changed the code.

I’d use the same approach for a stable business rule with a clear outcome. I’d be less eager to require it while trying different UI layouts. During exploration, I may still be deciding what the result should be. Building fixtures around each temporary choice can get in the way of finding it.

TDD is a development method. Running tests is verification. Tests written after implementation can still provide useful evidence. Neither order guarantees that an agent understood the requirement. It can write code and tests that agree with each other and are both wrong.

Give the agent room to choose, with limits

I’m trying to improve my skills and workflow instructions around that distinction. I want agents to choose checks that fit the change and explain the choice. I don’t want to approve every test, and I don’t want a fixed sequence followed just because it’s in a skill.

For a known bug, reproduce it with a focused test. For an exploratory change, time-box the experiment, inspect the result, then test the behavior worth keeping before shipping. Required validation still applies. Authentication, data loss, and duplicate payments don’t become optional because their tests are inconvenient.

When a failure appears, check what it protects before repairing it. Keep valid assertions. Fix stale setup. Replace or remove assertions only when the requirement changed or they add no useful coverage. Run the relevant broader checks once the change settles.

And when a tiny task turns into repeated fixture and mock repairs, stop and inspect the work. More tests aren’t automatically better verification.

The question I want in my workflow is simple. What would this check catch that still matters? If neither I nor the agent can answer that, adding another testing rule probably isn’t the fix.

All posts
Working on something similar? Email me