When Code Is Cheap, Tests Become the Real Product

By Ivan Kuznetsov
When Code Is Cheap, Tests Become the Real Product

Introduction

I remember when writing tests was a luxury.

When I was a CTO and co-founder of a small freelance agency called ArtMyWeb, we were doing lots of small projects from oDesk and Elance (they merged into Upwork at some point). The clients were typically non-technical. The budgets were super-tight. The hours were precious. Convincing them we needed to spend time on tests was always a hard sell.

From the client point of view, tests had no output. No button. No page. No feature. Just extra line items on the invoice. And very often the reply was straightforward: “If it works, why do we need tests?”

To get by, many teams — including ours — made compromises. Tests could be skipped in the name of speed. Especially when the inevitable startup pressure came knocking. We promised to come back to it later.

Later never happened. 🤓

Today, however, the terrain is very different. AI can write code faster than any human ever could. And strangely enough, that’s exactly why tests are needed more than ever.


This is not about vibe coding

Before going any further, let me be extremely clear about one thing.

This post is not about vibe coding.

I’m not talking about the process of throwing prompts at an AI, copy-pasting the output, and hoping for the best. That model has its place — but it’s for experimentation and demos. It’s far from suitable for building real systems.

I mean systems that you’d want to maintain, extend, and put trust in months or years from now. Systems where bugs are expensive, failures are visible, and correctness matters.

The AI definitely has a place in that world — but only if we give it structure and constraints. That’s the role of TDD.


Speed used to be the problem

Far too long, the biggest bottleneck in software development was human speed.

How fast can we write code? How many features can we deliver per week? How quickly can we respond to change?

Testing was seen by many as an impediment to achieving greater speeds. Even those who believed in tests often found themselves needing to defend their usage.

The usage of tests became a trade-off in people’s minds. Safety versus speed.

It was a sensible framing while coding was an expensive activity.


AI changed what “fast” means

Not anymore! AI code generation has turned that hypothesis upside down.

These days writing code is almost free. I can spend a few minutes describing a feature and get an implementation back in seconds — and it often looks better than I would have done it myself.

The downside? The AI has no idea if the code solves the right problem.

It’ll be more than happy to produce something that looks clean, professional, and convincing — while being subtly (or totally) wrong. And it’s this confidence that is most problematic for humans; we’re really bad at questioning things that look polished.

So the question is no longer “how fast can we write code?”

The question today is: how safely can we accept code written by a machine?


A humane, brief introduction to TDD

Not everyone is familiar with Test Driven Development, so here’s my simplest explanation.

TDD is a software development technique:

  • Write a test
  • Run it (and observe it fail)
  • Write just enough code to pass the test
  • Refactor

It’s the simplest thing in the world.

Despite its name, TDD is not really about testing. It’s about forcing yourself to define “correct behavior” before you write any code. The test encodes your intent.

And that’s precisely what AI needs.


Tests as contracts for AI

When I write a failing test first, something magical happens. I’m not just guiding my own thinking. I’m guiding the AI too!

A vague prompt like “implement user authentication” is easy for a human to make sense of. We excel at inference. AI does it randomly. A test isn’t vague though. It’s deterministic. This input must produce that output. No ambiguity.

The test is a contract.

The AI just has to comply.

Instead of asking the AI to “do the right thing”, I ask it to make the test pass. A subtle shift, but a powerful one.


Trusting behavior, not appearances

When I wrote my last article, “I Don’t Trust AI to Write My Code — But I Let It Read Everything”, I made my stance clear. At that time, I only trusted AI to read, analyze, and think about code.

I didn’t trust it to write any itself.

Things have changed since then.

I do trust AI to write code now. But only if one condition is met: The behavior is constrained by tests.

AI generated code looks good. The names are solid. The structure is professional. It’s hard not to take it at face value.

Tests give me the seatbelt.

With a sturdy test suite, I stop asking whether the code looks good. I stop relying on intuition. I just run the tests and check the behavior.

That’s a small but powerful mental shift. It trades belief for proof.


Feedback loops at machine speed

TDD already shortens feedback loops. AI renders them almost instantaneous.

I describe a behavior, implement it, test it, refine the prompt, repeat. It’s measured in minutes. Often seconds.

This doesn’t replace thinking. It amplifies it.

The quality of my tests drives the quality of the AI. Tests with errors produce faulty code. Tests with clarity produce surprisingly good code. Delegation doesn't disappear. It becomes more precise.


Conclusion

TDD didn’t die in the age of AI. It finally got a soulmate.

AI is absurdly good at writing code. TDD is absurdly good at specifying behavior. Together they form a workflow where speed and safety are no longer a contradiction.

We used to skip tests to go fast. Now, tests enable us to go fast and not crash.

In a world where infinite code can be written by machines, the one thing we should still be good at as humans is not typing. It’s being clear. Tests communicate that clarity — to the machines we can now collaborate with, and to ourselves.

When Code Is Cheap, Tests Become the Real Product