What Is Testing When the Machine Writes the Code
For twenty years the test pyramid told us the same thing. Pile up unit tests at the bottom, cheap and fast and stable, and keep UI and end-to-end tests to a minimum because they’re fragile and expensive. I think that pyramid is upside down now. And the reason it flipped tells us what testing actually is in the age of AI.
Why the pyramid flipped #
The thing that kept UI and end-to-end tests at the top, rare and reluctant, was never that they tested the wrong thing. They tested the right thing, which is real behavior from one end of the system to the other. We avoided them because they were costly to maintain. Brittle selectors, flaky flows, and hours of human time repairing them every time the UI moved.
That whole objection was about cost. And AI just collapsed the cost. Once generating and repairing a test is cheap, fragility stops being a reason to avoid a layer. The one weakness that justified keeping those tests scarce is the weakness AI happens to be good at absorbing.
So the top of the pyramid gets cheap at the same moment the bottom gets dangerous.
The case against unit tests, sharpened #
Here’s my actual opinion, and I’ll own it. In an AI-driven codebase, most unit tests are net negative. Let me give you the version of this that moved me, because it turns on the original reason unit tests exist, which was to control change.
Picture a routine refactor. You hand the agent a fresh instruction: switch our tax rounding to banker’s rounding for the new compliance rule. Along with that instruction, somewhere in the context, sits your test suite. And somewhere in your house rules is a line every shop has some version of: do not break the unit tests.
The agent makes the change and runs the suite. One test goes red. It expected 8.25 and got 8.24.
Stop on that red test and ask what it actually means, because there are two completely different answers and they look identical. The first answer is that you introduced a real regression, the test is right and your code is wrong, and the test just saved you. The second answer is that the rounding change was the entire point, the test is guarding the old behavior you deliberately asked to replace, and the test is now obsolete and should be removed. Same red bar. Same error message. Opposite meanings.
Now watch what the standing instruction does. A unit test is a frozen snapshot of past intent. Your prompt is the present intent. “Do not break the tests” is an instruction to privilege the frozen past over the stated present, and we hand it to the agent as though it were neutral safety advice. The harness cannot tell obsolescence from regression, so it reaches for something that satisfies both instructions at once. One option is to quietly revert your rounding so the test stays green, which silently undoes the compliance fix you asked for. It might instead leave the old code path alive beside the new one so nothing goes red, and now you own branching dead code. Or it simply deletes the test, which is the precise thing “do not break tests” was there to prevent, now done blind. The one move it cannot make reliably is the human one, which is to know which intent should win.
People will tell you this ambiguity is desirable friction, and sometimes it genuinely is. When you did not mean to touch that behavior, the red test catches you. But you cannot tune it. It fires exactly as hard when the change was intended as when it was a mistake, so it obstructs the refactor you wanted at the same rate it catches the bug you didn’t. Friction that fires the same whether you were right or wrong is a veto with no judgment behind it.
And all of that sits on top of the older problem. In an AI codebase the same model usually wrote both the implementation and the test, so a green checkmark only ever certified that the model agreed with itself. The fine-grained unit test, the one that mirrors your implementation, is the one most likely to be holding obsolete intent, and it is the first one I would delete.
So what do we actually test now? #
If the bottom of the pyramid is mirrors and the top just got cheap, where does the real signal live? Two places.
First, at the edges, through contract tests. You don’t need heavy integration coverage everywhere. You need tests exactly where your system touches something you don’t control, like a third-party API, a payment gateway, or another team’s service. Those boundaries are where reality lives, and reality is the one thing the AI can’t quietly rewrite to make a test pass. When the external contract changes, the test fails for a genuine reason rather than a manufactured one. That gives you ground truth, and contract testing is the precise instrument for it.
Second, at the core, through the transformation itself. Strip away the ceremony and AI engineering cares about three things: the input, the output, and whether the transformation logic is correct for the domain. The question is no longer “does this function return 4.” The question is whether the transformation preserves the business rules you actually care about. That’s the real unit of meaning now.
And the timing of testing multiplied too. Security and performance used to be a phase near the end of the work. Now they get checked agentically while the code is being built, again at merge time in CI/CD, and again on a schedule against the live system. Testing stopped being an event you run once and became a property you assert continuously.
That’s the modern picture. Mirrors deleted, edges pinned by contracts, domain transformations validated, and security and performance running agentically and continuously.
The new job of QA #
This leaves one honest question. If the AI writes the code, and the AI also writes the tests, then who watches the watchers?
I don’t ask that to score a point. I ask it because I think it points at a real and possibly growing role for human QA, just not the role we retired. The old QA job, a human hand-authoring test cases, got automated twice over. But the need that job served didn’t shrink. It got sharper. And I think it splits into three.
QA as keeper of intent. The AI can’t be trusted to define what should be true, because that’s the independent second judgment that just collapsed. A human owns the specification of correct and holds it deliberately apart from the thing being checked.
QA as adversary. The AI shares its blind spots with its own tests. Someone has to break what it can’t see, like the malformed input, the security corner, and the thing no reasonable user would ever do on purpose. This is exploratory and adversarial work, red-teaming your own product.
QA as domain oracle. Someone has to understand the domain well enough to say whether the transformation is right for the business, which is the exact thing input and output tests can’t capture and the thing the AI can’t verify about itself.
Keeper of intent, adversary, and domain oracle. These are the same jobs the old test suite quietly did for us, and now they need a human to hold them precisely because the machine writing both sides can’t.
So maybe the question for us isn’t whether AI will replace QA. Maybe it’s this. Now that the machine writes the code and grades its own work, what’s the smallest irreducible piece of judgment we can’t hand it, and is that piece actually the most important job in the building?
Michael (Mishka) Kofman is the founder of Paracorp, where he serves as a Fractional CTO helping organizations organizations modernize complex software systems, accelerate AI adoption, and build high-performing engineering organizations. He is also the founder of ARC, an AI-assisted legacy modernization platform, and Hidden OS, a personal AI operating system designed to augment human decision-making and life management. Michael brings 38 years of technology experience, including more than 15 years working in artificial intelligence, with expertise in enterprise architecture, distributed systems, cloud platforms, and software modernization. His career includes engineering and architecture leadership across startups, Fortune 500 companies, and government organizations, helping teams transform legacy technology into modern, AI-native platforms.