All posts

TDD finally makes sense

Published on

  • ai
  • webdev
  • architecture
  • process
  • career

AI coding tools have flipped the economics of test-driven development. Writing tests used to feel like a tax on your time. Now, with AI handling the grunt work of test scaffolding and implementation, TDD is both viable and essential. The developers who adopt it will build real software. The ones who don't will ship vibe-coded slop that falls apart at the edges.

The old excuse is dead

Let's be honest. Most of us who resisted TDD had a reasonable argument: it slowed us down. Writing tests before code when you're still figuring out what the code should do felt like building guardrails for a road you haven't designed yet. I get it. I lived it. I'm an iterative coder by nature - I like to sketch things out, see what emerges, and refine from there. Writing tests before I had a clear picture of the solution felt backwards.

That argument assumed a world where writing tests was expensive and writing code was the bottleneck. That world is gone.

AI coding tools have compressed the cost of writing both code and tests so dramatically that the old calculus no longer applies. If generating implementation code takes minutes instead of hours, and generating test scaffolding takes seconds instead of minutes, the time investment in TDD approaches zero. What remains is pure upside.

The inversion point

TDD has always been the preferred approach for producing higher-quality output. This isn't new wisdom. Kent Beck wasn't wrong. The problem was always practical: the discipline required more time than most teams felt they could afford, especially in fast-moving product environments where shipping mattered more than test coverage.

We've now hit what I'd call the inversion point. The time you save by using AI to generate code is so significant that reinvesting a fraction of that saved time into writing tests first isn't just affordable, it's the obvious move. You're net positive on time and dramatically positive on quality.

Think of it this way. Before AI tools, you might spend 4 hours writing a feature and then convince yourself you'd write tests later (you wouldn't). Now, you spend 30 minutes writing tests that define the expected behavior, and the AI generates the implementation in another 30 minutes. Total time: 1 hour. Better tested. Fewer surprises. And you actually have tests.

The vibe coding trap

I've built many apps with AI over the past year, and I've noticed a pattern. The speed is intoxicating. You describe what you want, the AI generates it, you run it, it works. Ship it. Next feature.

Then the hotfixes start.

At the pace AI enables you to build, you're also outrunning your own ability to reason about edge cases. The AI generated code that handles the happy path beautifully but falls over when a user submits an empty form, passes a null where a string was expected, or hits an API endpoint in an order you didn't anticipate. These aren't exotic scenarios, they're the boring, predictable stuff that tests catch.

This is what I call vibe-coded slop. It looks like a real application. It demos well. It passes a casual code review. But under any real-world pressure, it crumbles - because nobody defined what the software was supposed to do before asking the AI to build it.

The gap between a vibe-coded prototype and production software is test coverage. Not test coverage as an afterthought, test coverage as the starting point.

Why AI makes TDD click

Here's the part that surprised me. AI tools make TDD feel natural.

If you've used any AI coding assistant seriously, you'll recognize this workflow: you describe what you want to build, the AI asks clarifying questions (or you prompt it to), you refine the scope, and then it generates code. That planning phase, where you articulate intent, define expected behavior, and think through constraints, is already 80% of the mental work of writing tests.

The leap from "describe the feature to your AI tool" to "write tests that encode that description" is tiny. You're already doing the hard thinking. TDD just asks you to formalize it before the AI starts generating implementation code.

I used to skip writing tests first because I'm an iterative coder. I need to explore the problem space before I know what I'm building. But AI planning mechanisms have changed that dynamic. I can iterate on ideas in conversation with the AI before writing a single line of code. By the time I'm ready to implement, my thinking is developed enough that writing tests first actually feels right. The ambiguity that made TDD feel premature in my old workflow is resolved before the TDD cycle even begins.

A practical workflow

Here's what this looks like in practice.

Plan first, test second, code third. Start with your AI tool in planning mode. Describe the feature or module you're building. Ask it to identify edge cases, failure modes, and expected behaviors. Don't accept the first answer, push back, add constraints, think about what users will actually do. This conversation becomes your test specification.

Write the test file. Take the planning output and write (or have the AI write) a test file that covers the happy path, the edge cases, and the error states you identified. These tests will fail. That's the point.

Generate the implementation. Now let the AI write the code. But instead of the usual "build me a function that does X," your prompt is "make these tests pass." The AI has a concrete contract to fulfill, which dramatically improves the quality of generated code.

Run, fix, iterate. Run the tests. Some will pass. Some won't. Fix the failures, sometimes by adjusting the implementation, sometimes by realizing your test was wrong (which means your understanding of the feature was wrong, which is valuable to discover now rather than in production).

Resist the urge to skip red-green-refactor. The temptation with AI is to generate everything in one shot and move on. Fight that urge. The red-green-refactor cycle exists because it forces you to confront what your software actually does versus what you assumed it does.

The quality divide is coming

Here's my prediction. Over the next year, we're going to see a clear split in the AI-assisted development world. On one side, developers who use AI for speed but anchor their work in tests and defined behavior. On the other, developers who accept whatever the AI generates and ship it.

The second group will produce a lot of software very quickly. Most of it will be mediocre. Edge cases everywhere. Security holes from generated code that nobody scrutinized. Features that work in the demo but break in production. This is the inevitable outcome of speed without verification.

The first group will ship slightly slower per commit but dramatically faster per working feature. Their codebases will be maintainable. Their deployments will be predictable. Their hotfix rate will be a fraction of the vibe coders.

The thing that distinguishes software built with intention from software built with vibes.

It's not all sunshine and rainbows

I want to be practical here. TDD with AI isn't a silver bullet. You still need to write good tests, and AI-generated tests can be just as shallow as AI-generated code if you don't guide them well. A test suite full of trivially passing assertions is worse than no tests at all because it gives you false confidence.

The discipline still matters. AI makes TDD economically viable, but it doesn't make it intellectually free. You still need to think carefully about what to test, how to structure your test suite, and when a test is actually validating something meaningful versus just checking that the code you wrote does what you wrote.

That intellectual work is exactly the work that matters most in an AI-assisted development world. When the AI can generate implementation code faster than you can type, your competitive advantage shifts entirely to decision-making: what to build, how it should behave, and what the edge cases are. TDD is the discipline that forces those decisions to the front of the process rather than leaving them as afterthoughts discovered in production.

Concluding

We've spent years treating TDD as something virtuous but impractical - the broccoli of software development. Everybody agreed it was good for you, but nobody wanted to eat it.

AI has changed the equation. The time cost that made TDD impractical has evaporated. The speed that makes AI-assisted development powerful has made TDD essential. And the planning workflows that AI tools encourage have made TDD feel natural for the first time.

If you're building software with AI and you're not writing tests first, you're vibe coding. Your app might work today, but it won't hold up. The developers who embrace TDD in this new AI-assisted reality will build the real applications. The ones who don't will build impressive demos that fall apart the moment a real user touches them.

The inversion point is here. TDD finally makes sense. Don't waste it. Until we have AGI and none of these musings matter anymore...

Frequently asked questions

  • Why does AI make test driven development more practical now?

    AI dramatically reduces the time required to write both implementation code and test scaffolding. What used to feel like a heavy upfront investment now takes minutes, so the relative cost of writing tests first is close to zero. You can spend a short planning phase with an AI assistant to define behavior and edge cases, then turn that into tests and have the AI generate code to satisfy them. This flips the economics of TDD from a perceived slowdown to a net time saver with much higher quality output.

  • What is vibe coded slop and why is it dangerous?

    Vibe coded slop is software generated quickly with AI that appears to work, demos well, and passes casual review, but lacks clearly defined behavior and robust test coverage. It typically handles only the happy path and fails on predictable edge cases like null inputs, unexpected API sequences, or invalid user data. Because nobody specified what the software must do before building it, problems surface later as hotfixes and production incidents. The gap between such prototypes and reliable production software is disciplined, meaningful test coverage.

  • How should I structure a practical AI assisted TDD workflow?

    Start by using your AI tool purely in planning mode. Describe the feature, ask it to enumerate edge cases, failure modes, and expected behaviors, and iterate on that until it feels solid. Next, turn this specification into a test file that covers happy paths, edge cases, and error states; these tests should initially fail. Then prompt the AI to implement code with the explicit goal of making those tests pass. Finally, run the tests, fix failures, refine tests or implementation as needed, and follow the red green refactor cycle rather than generating everything in one shot.