PORTFOLIO
Back to writing

AI

AI Didn't Make Me Write Better Code — It Made Me Finally Write Tests

July 8th, 20263 min read
AI Didn't Make Me Write Better Code — It Made Me Finally Write Tests

When I joined one of my projects, automated test coverage was basically zero. Classic story: tight deadlines, "we'll add tests later," and later never comes.

Here's the thing most people get wrong about why codebases have no tests. It isn't a skill problem. It's a friction problem. Writing tests retroactively is miserable, so nobody does it. The activation energy is too high.

AI changed that for me — but not in the way the hype suggests.

What didn't work

The first instinct is "AI, write all my tests." Don't. You get a wall of plausible-looking tests that assert the wrong things, test implementation details instead of behavior, and break the moment you refactor. You end up trusting coverage that's actually hollow.

What actually worked

I started scaffolding tests right after shipping a feature, while the logic was still fresh in my head. The workflow:

  1. Write the feature.
  2. Tell the AI the specific edge cases I care about — not "write tests."
  3. Read every generated test.
  4. Fix the wrong assumptions, delete the useless ones.
  5. Keep the ~60% that's actually correct.

The AI removes the blank-page friction. I keep the judgment.

The prompt that works

Instead of "write tests for this function," I describe behavior and edge cases:

Here's a function that calculates a golf handicap from a list of scores. Write Jest unit tests covering: - empty score list - fewer scores than the minimum required - scores with invalid/negative values - the normal happy path with 20+ scores Test behavior and return values, not internal implementation.

The difference is night and day. Specifying edge cases forces the AI to produce tests that actually mean something — and forces me to think about what could break.

The edge cases I always check

Regardless of the feature, these are the ones AI tends to skip unless you name them:

  • Empty inputs (empty array, empty string, null/undefined)
  • Boundary values (0, max, one-below and one-above a limit)
  • Invalid types and malformed data
  • Concurrent or out-of-order operations (especially for anything event-driven)
  • The unhappy path — what happens when the API call or DB write fails

Before / after

Before: near-zero coverage, every refactor a leap of faith, production bugs caught by users.

After: 70%+ coverage on the critical paths over a few months. Not because AI is magic — because it killed the friction that kept tests from ever getting written.

The actual lesson

Don't use AI to replace your judgment. Use it to remove the boring barrier between you and the work you already know you should do. The hard part of testing was never the logic. It was starting.

Related

More to explore

July 20th, 2026

What I Let AI Write, and What I Never Will

After a year of Claude Code in my daily workflow, here's the honest version of how AI fits into real engineering work — the tasks I hand it without hesitation, and the ones I'll never let it own.

AI ToolsSoftware EngineeringDeveloper ProductivityEngineering Practices
Read article

April 15th, 2026

Instrumenting Production Apps: Mixpanel, Sentry, and Cypress in Practice

A practical setup for knowing what users actually do, catching errors before users report them, and trusting your own deploys.

TestingObservabilityDX
Read article