The TDD (test-driven improvement) workflow can be utilized with AI-augmented coding in a number of methods:
- Human writes the assessments: A human defines the check eventualities in some kind, be it in pure language, in BDD model, or instantly in code. Then AI writes the implementation to make these assessments move (with perhaps a primary step that transforms the human’s eventualities into code).
- Overview checkpoint for the human: AI writes a failing check, human appears at it to evaluation that the check is testing the needed conduct, then AI writes the implementation
- Totally contained in the agentic loop: Immediate an agent to put in writing failing assessments first, one after the other, after which write the implementation and test that the beforehand failing check is inexperienced.
At this stage, that final utilization is by far the most typical one. However does it actually make a distinction, asking an agent to observe a TDD workflow absolutely inside its personal loop? Does it actually present worth, or is it one of many uncommon examples the place what’s good for the human may be irrelevant or dangerous for a coding agent?
I created an exploratory analysis setup to scratch the floor of this query and see what I might discover. It’s removed from a complete and structured eval consequence, but it surely did create some hypotheses to consider if you’re working onerous to get your agent to make use of TDD.
TLDR; Primarily based on Opus’s judgment of the standard of the outcomes, there was no clearly discernable distinction based mostly on TDD workflow versus no TDD workflow. Quite the opposite, greater than as soon as Opus ranked the non-TDD workflow options barely larger in design and check high quality. There was additionally no significant distinction in mutation scores throughout the options.
The setup
- Duties: I created a small, medium and a bigger process with the assistance of Claude, all inexperienced subject implementations of a little bit of enterprise logic. I had it make a bunch of ideas, asking for idiosyncratic and particular logic to extend the likelihood that there might be variance between options, and never only a repetition of one thing that’s already dominant within the coaching knowledge.
- Directions: In all runs, I included directions to attain at the least 80% code protection.
- Mannequin: I used Sonnet 4.6 to generate the options.
- Judgment of TDD adherence: Analysis of adherence to TDD was additionally completed by Sonnet 4.6.
- Judgment of options: Opus 4.8 in contrast the standard of each options and their assessments, with out information of how the options had been created. I did not give very particular inputs on what I think about to be good high quality, as this was a really open exploration. And in my expertise, the extra particular I might have gotten, the extra the mannequin may have over-indexed unnecessarily on the standard standards I record. Opus has proven to be fairly a succesful mannequin when it comes to judgment of code high quality. For its rating of the options, it created a rubric on the fly to move to all subagents that had been evaluating the person options.
If you draw your personal conclusions from my outcomes, the primary caveats to think about are:
- That is clearly a really small pattern dimension, so take it with a grain of salt
- Judgment of what “high quality” means was virtually absolutely left to Opus (with just a few pointers about check high quality)
- Not one of the runs ever adopted TDD completely, however fairly nicely
- The coding duties given to the brokers had been all greenfield and comparatively small, purely about enterprise logic
How good are brokers even at TDD?
Earlier than I even began, I wanted to verify the TDD directions had been truly adopted. Traditionally that hasn’t gone nicely for me: brokers typically write the implementation first and generate assessments after, skip confirming the purple step, or over-implement forward of the present check so the subsequent one passes with out ever going purple.
The immediate I ended up utilizing labored nicely sufficient with Sonnet to make use of for the comparability, although all periods confirmed a few of these failures to an extent. For every TDD run, I had an impartial agent choose how nicely the workflow was adopted, based mostly on the session transcript, in order that I would not by accident take into consideration a run that did not meaningfully do it.
Outcomes
I created 5 batches of options, with two non-TDD and two TDD options every. In a single batch, I additionally added two runs that had been instructed to put in writing the assessments first, with out full TDD self-discipline (no incremental purple/inexperienced).
Throughout the small (1 batch) and medium (3 batches) duties there was a little bit of a sample: Opus ranked the 2 non-TDD options #1 and #2, and the 2 TDD options #3 and #4. Solely as soon as – after I strengthened the TDD immediate with a extra specific refactor-and-design-review step – did a TDD resolution rank #1. In that very same batch, the opposite TDD resolution, run with the equivalent immediate, ranked final although… For the bigger process, TDD landed within the center, whereas the 2 non-TDD runs took each one of the best and the worst spot.
(Particulars within the appendix)
Hypotheses
So in abstract, each TDD and non-TDD scored each as a finest and a worst resolution throughout the batches, with TDD total performing barely worse.
Requested to take a look at the session traces to hypothesize concerning the outcomes with information of which workflow was used for which, Opus discovered that the non-TDD and test-first runs all the time created the complete design (structure, knowledge varieties, edge instances, contracts) earlier than writing any code or assessments, fairly than working by way of it one requirement/check at a time. That appeared to be the factor that moved the needle barely in direction of comparatively higher knowledge fashions, extra cross-cutting edge instances, and higher completeness of the performance.
The TDD directions actively work towards such an up entrance design step. The design in these runs emerged from the sum of many locally-minimal choices and was hardly ever revisited, so it tended to land on no matter form the primary check occurred to lock in. Behaviour the agent did not assume to put in writing a check for did not get carried out in any respect.
After I chatted to Ivett Ördög about this, she had this concept: “The way in which AI brokers had been skilled is that they’ve seen accomplished capabilities and descriptions of these capabilities. The variety of precise step-by-step TDD examples they’ve seen is a tiny a part of the coaching knowledge. That signifies that the LLM has an inner illustration of code that may be a direct translation of necessities to code, and never a technique of how one can get to that illustration.”
Targets of TDD – nonetheless achieved within the agent loop?
The next are my common reflections about utilizing TDD within the agent loop, not solely based mostly on this experiment. I am going by way of the final word targets I personally have once I use TDD, skipping a number of the ones which can be about having assessments within the first place, and unit assessments particularly (like refactoring security internet, residing documentation, check protection), focussing on those which can be particular to the TDD workflow.
Check first >> Avoiding tautology
Check-first makes it simpler to claim the output I need, fairly than restating the implementation. Such a check can by no means fail when the implementation is improper because it was derived from the identical logic it is supposedly checking. When the assertions are decoupled from the precise implementation path, the check can truly catch when the behaviour isn’t what I meant.
Nonetheless achieved within the agent loop?
In my experiment, some TDD periods had this downside anyway, regardless of writing the check first. In a single notably apparent instance, assessments checked the implementation’s output towards itself, re-running the identical code to provide the “anticipated” reply (see 4. on this record of observations). Writing the check first does not reliably stop this – it would make it much less possible, which is all we are able to ever hope for anyway with LLMs, however from this small knowledge set I can not draw any conclusions about that likelihood.
Check first >> Testability
Check-first ensures the code is designed to be testable from the beginning, fairly than retrofitting assessments which can be extra complicated and brittle than vital.
Nonetheless achieved within the agent loop?
The outcomes did not give me any clear reduce indicators both method. For what it is value, the scale and nature of the duties I selected did not require loads of design complexity that might have surfaced this. To an extent although, testability is a corollary to driving design (see beneath).
Pink-green >> Check effectiveness
Observing a check fail first, then succeed (red-green), proves it’s going to truly catch a regression.
Nonetheless achieved within the agent loop?
How a lot sense does this actually make when the human is eliminated? Watching a check go purple is simply proof of something if somebody is checking why it went purple. When the agent each writes the check and confirms it failed, a purple check tells you the agent ran it and noticed failure, not that the failure was for the precise motive. The evaluations of TDD adherence in my experiment additionally present this: brokers nonetheless generally skipped or faked the purple step, or carried out forward of the check in order that it handed instantly. Regression effectiveness could be monitored and improved with mutation testing (as I wrote about right here). Mutation scores throughout the options did not present any indicators that TDD runs produced meaningfully higher mutation scores than non-TDD runs. I do not actually care how regression high quality was achieved, so long as I’ve a mechanism to see how good it’s.
Check first, red-green-refactor >> Driving higher design
Writing the check first forces us to specify utilization earlier than implementation, pushing towards higher interfaces and extra modular code. The refactoring step within the TDD loop additional pushes us to enhance the design step-by-step.
Nonetheless achieved within the agent loop?
The experiment at the least hasn’t demonstrated superior design within the TDD runs in any respect. I now even surprise if TDD makes it worse, based mostly on Opus’s scoring, because the non-TDD options as a rule had been ranked larger, and the design flaws it listed made sense to me. However the knowledge set is in fact too small to definitively conclude something. (If anyone has time and tokens to run a bigger experiment, that might be very fascinating!)
When people write a check first, it forces us to consider utilization earlier than implementation, we’ve to sit down with the friction of specifying behaviour and expectations earlier than realizing how one can construct it. An agent does not expertise that and might write a check the identical on the spot it plans an implementation. With no human checkpoint between the 2, is there actually any objective left to writing the check first?
Small steps >> YAGNI
Writing solely sufficient code to move the subsequent check is about restraint. It is imagined to cease us from constructing abstractions or dealing with instances no person has requested for but.
Nonetheless achieved within the agent loop?
This can be a very human-centered profit that will get misplaced when an agent does TDD by itself. We do not get to sit down in that friction anymore the place we actually have to consider all of the intricacies of what we’re constructing. That’s theoretically shifting to once we are writing the specs to offer to an agent, however we do not have a TDD-like mechanism there that lets us assume the spec by way of in small steps.
Could not an agent work in these small steps although and ask us questions every time it finds one thing that may be pointless? In my common expertise, they don’t seem to be excellent at that. And within the experiment as nicely, minimal-implementation directions did not reliably cease them from constructing extra. They steadily overshot and carried out greater than the present check demanded, as a result of that they had the complete requirement accessible. We normally do not spoon-feed the spec one after the other, that might be very inefficient.
Small steps >> Quick, localized suggestions
Taking one small step at a time signifies that when a check fails, I do know virtually precisely what precipitated it, as the one factor that modified because the final inexperienced state is the one factor you simply wrote.
Nonetheless achieved within the agent loop?
The setup did not present if brokers obtained caught debugging extra steadily with versus with out TDD. However in my common expertise, brokers are normally fairly good at determining why a check is purple, even with out having taken small, deliberate steps to get there. I am nonetheless uncertain if the occasions after they do get caught might be meaningfully mitigated with small TDD steps, and if the general price/profit comparability would maintain up.
Small steps >> Confidence and studying
In Kent Beck’s preface to “Check-driven Improvement by instance”, his largest rationale for TDD is “managing worry”. He says that the official worry of onerous issues makes builders tentative, much less communicative, and avoidant of suggestions. With TDD, every passing check exhibits us progress, so we are able to chill out realizing that progress is locked in. The assessments are a psychological mechanism that helps us preserve going.
Nonetheless achieved within the agent loop?
That is very a lot about managing a human’s worry and giving a human permission to chill out. That does not switch when the agent is doing TDD within the loop, because it does not give me the identical management and belief as once I do it myself, step-by-step.
Prices
At the least 3x the tokens
See detailed numbers within the appendix.
Naturally, as a TDD workflow requires many extra turns and gear calls, extra tokens might be used. Nonetheless, a lot of these might be cache hits, so notice that the 3x or extra issue of tokens aren’t a direct illustration of how rather more expensive it’s. (Sadly, I did not monitor cache hits through the experiment.)
Immediate upkeep and testing
TDD is a course of that does not appear to “come pure” to fashions. It is like an uphill battle towards the coaching knowledge, and takes loads of iterations on a immediate to get it to observe the method more often than not. For instance, once I realised after my first batches that the agent did not do a lot refactoring within the red-green-refactor loop, I modified the immediate to place extra emphasis on that step, because it’s in fact essential to TDD. I later requested Opus to take a look at these periods and see if it discovered an enchancment in refactoring efforts. It did report a rise in refactoring steps – nevertheless, it additionally listed some instances through which the agent got down to refactor, however determined the design was adequate even in instances the place Opus thought it clearly wasn’t (e.g. when the whole lot was carried out in a single huge module, however may have clearly been break up up into a number of tasks).
TDD is a relatively complicated set of directions with a lot of variables, and consequently a lot of variations in how brokers interpret it. So I think about the sort of immediate to be much more unstable throughout fashions than easier directions are, which means it takes effort to maintain the immediate working throughout fashions and mannequin releases.

My conclusions
I feel at this level there’s typically increasingly proof that being overly particular about how we wish a mannequin to do one thing isn’t a sustainable strategy. As a substitute, we should always discover as some ways as we are able to to observe the outcomes and provides suggestions. That suggestions needs to be automated wherever potential, and we have to fastidiously take into consideration the place we insert ourselves as arbiters of what’s good and proper.
Despite the fact that I’m conscious that my little eval is way from representing a broad perspective on the effectiveness of TDD, it undoubtedly hasn’t given me any new indications that each one this effort is value it. Particularly not if we are able to discover different methods to attain the vast majority of TDD advantages.
I personally have stopped telling my coding brokers to put in writing assessments first, not to mention do TDD (which I by no means did, to be trustworthy), till I see evals or different sturdy arguments that persuade me in any other case. I am attempting to focus as a substitute on the advantages of TDD once I use it exterior of the agent loop, and exploring alternative routes to attain them.
The right way to get good regression assessments?
…in order that the agent and me get indicators when present performance breaks
I nonetheless care about stable regression assessments, as a result of though an agent can in fact repair purple assessments the improper method round, at the least the purple check provides it a suggestions sign to double test pre-existing necessities that may have damaged. I monitor and enhance regression high quality with the assistance of mutation testing, as a substitute of giving elaborate TDD directions and hoping for one of the best.
The right way to construct common refactoring into the method?
…in order that the codebase stays straightforward to vary
Refactoring stays essential, however the small steps of conventional TDD aren’t an environment friendly or efficient solution to do it within the agent loop. Just a few examples of triggers for refactorings: Give the agent entry to static code evaluation; run common evaluations of construction and modularity; develop staff rituals to take care of a great understanding of the codebase and catch drift early; control the development of variety of information touched per change, and variety of tokens are for a change.
The right way to get confidence?
…in order that I’m not afraid to push to manufacturing
The toughest query stays, how can we get that confidence that TDD was giving us, how can we handle worry, how can we lock in progress? I haven’t got a transparent reply to that, however I am going to simply point out one of many issues that looks like a great constructing block for that: I’ve not too long ago tried out the Accepted Situations strategy that Ivett Ördög is advocating for. In my phrases (do not maintain her to it), it is a type of semi-manual testing that’s supported by a bespoke check runner for every utility. That runner exhibits me useful check eventualities in a simple to consider method, and permits me to “freeze” expectations (eventualities / fixtures) in that runner after I’ve totally confirmed them. Every time these frozen expectations are violated sooner or later, I’ve to approve them once more. My colleague Matteo Vaccari gave an excellent overview of his experiences with that strategy right here.
No matter finally ends up giving us belief and confidence in our software program sooner or later – I feel the position of TDD as we have recognized it’s considerably smaller than pre-GenAI.
