Testing AI-Generated Code: A Strategy for Reviewing Autonomous Coding Output

Most articles about AI coding agents stop at "and then the agent wrote the code." But code generation is the easy part. The hard part — the part that separates a working pipeline from a novelty — is verification.

If you can't trust what the agent produces, you have to read every line yourself. And if you have to read every line yourself, why bother running the agent at all?

The three-layer review strategy

After running unattended coding workflows for months, I've settled on a three-layer approach:

Layer 1: Automated verification (the gate)

Before a human even looks at the output, automated checks should catch the obvious failures:

Tests pass. The agent's job isn't done until the existing test suite passes. If it added features, the new tests it wrote also need to pass.

Type checking passes. mypy, pyright, tsc — whatever your language uses. If the type checker fails, the agent didn't produce valid code.

Lint passes. ruff, eslint, clippy. If the linter finds things, the agent shipped sloppy output.

These three checks together catch roughly 40–60% of AI-generated defects. They cost almost nothing and run in seconds.

Layer 2: Differential review (the sanity check)

This is where you compare the agent's output against a second opinion:

Run a different model on review. Send the agent's diff to Claude Sonnet with a prompt like "Review this diff for bugs, edge cases, and security issues." A different model catches different failure modes.

Property-based tests. Instead of hand-writing test cases, define invariants ("this function should never return null," "sorted output must be monotonic"). Let the property-testing framework generate inputs.

Snapshot testing. If the agent refactored code without changing behavior, the snapshots should be identical. If they changed, investigate why.

The key insight: you don't need to review every line. You need to verify that the behavior preserved what you expected and that new behavior is thoughtfully tested.

Layer 3: The review budget (the human gate)

Here's the concept that changed how I think about AI code review:

Review budget = time saved by agent × 0.2 (cap at 20 minutes)

If an agent saved you 4 hours of coding, spend 48 minutes reviewing. If it saved you 15 minutes, spend 3. The ratio forces you to decide: was this task worth automating?

The review budget also prevents the most common failure mode — spending 30 minutes reviewing a 10-minute task. If your review time exceeds your coding time, the agent didn't help.

What to look for in AI-generated code

Some failure modes are unique to AI-generated code:

Failure mode | How to catch it | Automated?
Hallucinated APIs | grep for function names that don't exist in any import | ✅
Swallowed exceptions | grep for except: pass or catch {} with no body | ✅
Cargo-culted patterns | Look for patterns from tutorials applied to problems they don't fit | ❌ Human
Over-engineering | Simple task, complex abstraction hierarchy | ❌ Human
Context truncation bugs | Missing edge case handling in the second half of a long function | ❌ Human
Stale assumptions | References to code that was changed in a different part of the diff | 🔶 Diff-level grep

The automated checks (layers 1 and 2) catch the first two completely and partially catch the last one. The human budget (layer 3) covers the middle three.

How Ralph Workflow structures this

Ralph Workflow is a free, open-source orchestrator that bakes this three-layer review into every run:

The run phase generates code

The verify phase runs your test suite and linters automatically

If verification fails, the fix loop sends it back to the agent with the failure output

Only when all gates pass does the output land in your working directory

[phases.development]
agent = "claude-code"
model = "claude-sonnet-4-20250514"

[phases.verify]
agent = "claude-code"
model = "claude-haiku-4-20250514"
prompt = "Review the diff for: bugs, missing edge cases, security issues, API misuse. Be specific."

[phases.fix]
agent = "claude-code"
model = "claude-haiku-4-20250514"
max_iterations = 3

This means the agent doesn't just write code — it writes code that passes verification. If it can't pass, it stops and tells you why.

Getting started

pip install ralph-workflow
ralph init my-project
ralph run --task "Add input validation to the signup form"

The verification phase runs your test suite automatically before handing off. If you don't have a test suite, the agent writes one as part of the task — you just need to specify what "correct" means.

Primary repo (Codeberg): codeberg.org/RalphWorkflow/Ralph-Workflow
Mirror (GitHub): github.com/Ralph-Workflow/Ralph-Workflow
Docs: ralphworkflow.com/docs

The review-budget concept and three-layer strategy come from running unattended coding workflows in production. These patterns are tool-agnostic — they work with any AI coding agent, whether you use Ralph Workflow, Claude Code directly, or a custom pipeline.