Testing AI Written Code: A Simple Routine That Catches Most Bugs

· 6 min read · Guides

Testing AI Written Code: A Simple Routine That Catches Most Bugs

The simplest way to test AI-written code is to decide what "working" means before you prompt, run the thing yourself, and make the agent prove it with tests you've read. Then lock in every bug you find with a regression test. It takes about ten minutes per feature once it becomes habit.

You don't need a QA background or a big test suite. You need a routine you will actually follow when the agent says "Done!" and you want to move on.

Why "it runs" isn't enough

AI code usually compiles and often looks tidy. That is the trap. It reads like someone thought it through, but nobody checked the assumptions inside it.

Security is the clearest example. Veracode's 2026 research update found that the share of code-generation tasks producing detectable vulnerabilities fell from about 44% to 38%. That's real progress, and it still means roughly four in ten tasks came out with a flaw when the models weren't given explicit security instructions.

So the goal isn't to distrust the tool. It's to stop treating "no red errors" as proof.

The routine at a glance

StepWhat you doRoughly how long
1. Define doneWrite 3–5 plain-English behaviors before prompting2 min
2. Smoke testUse the feature yourself, including a few ways to break it3 min
3. Real testsTests from your behaviors, confirmed failing first, assertions read by you3–5 min
4. One commandLint, types, build and tests in a single checkSet up once
5. Fresh-eyes reviewA separate session reviews the diff2 min
6. Lock it inEvery bug becomes a regression test1 min per bug

Those times are my rough guess, not a benchmark. Your mileage will vary with the size of the change.

Step 1: Define "done" before the agent writes anything

Write the behaviors in your own words, in the prompt or a scratch file. Keep them about what a user sees, not how the code works.

  • A logged-out user who opens /dashboard is redirected to login.
  • Submitting the form with an empty email shows an error and saves nothing.
  • Two quick clicks on "Pay" create one order, not two.

This matters because the checks need to stay independent of the generated implementation. If you let the agent decide what "correct" means after it has written the code, it will happily agree with itself.

Step 2: Smoke test it like a slightly clumsy user

Run the app. Do the happy path first. Then spend two minutes being annoying:

  • Leave fields empty. Paste something huge. Paste <script>alert(1)</script> into a text box.
  • Refresh mid-action. Hit the back button. Double-click every button.
  • Open it logged out, or as a second user, and try to reach the first user's data.
  • Turn off your wifi, or break the API key, and see what the screen does.

Failure paths are where AI code tends to be thin. One testing guide specifically recommends explicit tests for failure cases like timeouts, connection failures, invalid responses and rate limits on every external call. Your manual poking is the cheap version of that.

If you're in a browser-based builder like Lovable, Bolt or v0, this step is most of your testing, so don't skip it. Click through the preview, then click through the deployed version, because they sometimes differ.

Step 3: Get tests, and read them

If your tool can run commands (Claude Code, Cursor's agent, Windsurf, Replit's agent), have it write tests from your Step 1 list. Anthropic's own guidance for Claude Code lays out a sequence that works in any agent. Write tests from expected input/output pairs, run them and confirm they fail, then have the agent write code that passes while told not to modify the tests.

The "confirm they fail" part is the one people skip. A test that has never failed might not be testing anything.

Then read the assertions. This is the human part you can't hand off. Ask of each one: does this encode what the feature should do, or just what the code currently does? Watch for tests that only check a mock was called, or that assert something that is always true. A write-up on testing agent code calls these tautological tests, and says to avoid letting the same model write both the code and its tests without independent checks.

If you can't write a test yourself, you can still do this: ask the agent to explain each test in one sentence. If the explanation sounds vague, the test is vague.

A prompt you can paste

Before changing any code, write tests for this feature based on
the behaviors below. Test user-visible behavior, not implementation
details. Include: empty input, invalid input, logged-out access,
and what happens when the external call fails.

Run the tests and show me that they fail. Then implement the
feature. Do not edit the tests to make them pass. When done, give
me the exact command you ran and its output.

Behaviors:
1. ...
2. ...
3. ...

The last line is deliberate. "Show me the command and output" turns a claim into evidence.

Step 4: Make one command that checks everything

Tests alone miss sloppy stuff. Types and linters catch a different class of problem. Wire them together so you (and the agent) run one thing.

"scripts": {
  "check": "npm run lint && npx tsc --noEmit && npm run build && npm test"
}

Adjust that to your stack; it's an example, not a requirement. Then put one line in your agent's instructions file (CLAUDE.md, Cursor rules, whatever you use): "Run npm run check before saying a task is complete." Specific beats vague here. One guide on Claude Code setups makes the same point: an instruction like "Run npm test before reporting completion" works better than "test your work thoroughly."

If you have GitHub, run the same command in CI so a red check blocks the merge. Then it doesn't depend on your mood at 1 a.m.

Step 5: Get a second opinion from a fresh session

The session that wrote the code is the worst reviewer of it. Open a new chat or agent with no history and give it only the diff and your Step 1 list.

Review this diff as a skeptical senior engineer. Don't assume
it works. List: (1) behaviors from my list that are not covered,
(2) places user input reaches the database, HTML or shell without
validation, (3) missing error handling, (4) any secrets or keys
in code. Be specific, with file and line.

Anthropic describes having one Claude write code while another reviews or tests it as a simple but effective approach. It won't catch everything. It's cheap, and it often finds the thing you'd have found in production.

Step 6: Turn every bug into a test

When you find a bug, in Step 2 or three weeks later, don't just ask for a fix. Ask for a failing test that reproduces it, then the fix, then proof the test passes.

This is how your suite grows without you planning it. After a month you have tests for exactly the things your agent tends to get wrong in your project.

What to test harder

You don't have time to deeply test everything. Spend extra effort here:

  • Auth and permissions. Can user A see user B's data?
  • Money and anything irreversible. Payments, deletes, emails sent to real people.
  • User input going anywhere. Databases, HTML, file paths.
  • Anything involving timing. Double submits, retries, background jobs.
  • Dependencies. Did the agent add a package you don't recognize? Check it exists and is maintained.

Boilerplate pages and simple styling can get a quick look and move on.

Common mistakes

  • Chasing coverage numbers. A high percentage from AI-written tests can mean little if the assertions are weak.
  • Letting the agent edit failing tests. If a test goes red, the question is whether the code or the test is wrong. Decide yourself.
  • Testing once. Agents change files you didn't ask about. Re-run the check after every round of changes.
  • Skipping the deployed app. Environment variables and build settings break things that passed locally.

FAQ

Can I let the AI write the tests for its own code?

Yes, with guardrails. Give it your behaviors to write tests from, make it show the tests failing first, and read the assertions yourself. Don't ship with only AI-written tests you haven't looked at. At least one assertion should come from your own idea of correct.

I can't code. How do I test AI-written code?

Lean on Steps 1, 2 and 5. Write behaviors in plain English, try to break the running app by hand, and use a fresh AI session as a reviewer. Ask the agent to run the tests and show you the command and output, and ask it to explain any test you don't follow.

How much testing is enough for a side project?

Match it to the damage a bug could do. A personal to-do app needs a smoke test and one check command. Anything with logins, payments or other people's data deserves tests on those paths specifically, plus a security-minded review before you launch.

Cover photo: Arnold Francisca on Unsplash

// the weekly drop

5 app ideas nobody built yet. Every week.

Real problems people complain about, who would pay, how hard it is to build, and the prompt to start with. Free.

One email a week. Unsubscribe in one click.