Skip to content
automationai-strategyqa-who-builds

How to Test AI-Generated Code Without Losing Your Mind

📅 2026-03-09âąī¸ 9 minâœī¸ By Oleg Neskoromnyi

I'm a QA engineer who decided to start building things. Not because I suddenly became a developer — but because AI tools like Cursor and Claude Code made it possible for someone with testing instincts and zero React experience to ship real projects. I've been learning by doing: building tools, breaking things, shipping too early, and figuring it out as I go.

One of those projects needed authentication. I used Cursor to generate the middleware — token validation, role-based access, session handling. The code looked clean. Good variable names, solid structure, helpful comments. It passed the tests I had. The linter was happy. I shipped it.

Two weeks later, I discovered the middleware wasn't checking token expiration. It validated the signature, verified the role, confirmed the session — and let expired tokens through without a word. The AI had generated code that handled every case except the one that mattered most.

AI-generated code doesn't signal its weaknesses the way rough, early-stage code normally does. There's no messy formatting, no uncertain naming. The output is confidently wrong in ways that resist casual review — especially when you're a solo builder moving fast.

Here's the irony: I'm a QA engineer. Catching bugs is literally what I do for a living. But when I became the builder, I trusted the AI's output more than I should have. I was so focused on learning and shipping that I skipped the discipline I'd spent years developing.

That incident changed how I test AI-generated code. Not by slowing down — I still move fast and break things. But I built a system that catches what my quick reviews miss. Here's what I use now.

Why AI-Generated Code Needs a Different Testing Approach

When you're building with AI as a solo developer, the normal safety nets don't exist. There's no code review from a teammate. No senior developer catching what you missed. No QA engineer reviewing your work — because you are the QA engineer, and you're too busy building to switch hats.

AI code makes this worse because it looks like it was written by someone who knew what they were doing. The model generates what looks statistically correct based on patterns, not what's logically complete for your specific project.

This isn't just my experience. The companies building these AI models are telling us the same thing.

Anthropic's Frontier Red Team — a group of about 15 researchers who stress-test Claude — recently found over 500 vulnerabilities in production open-source codebases. These were bugs that had gone undetected for years despite expert human review. If code written by experienced developers carries hidden vulnerabilities, imagine what's hiding in code generated by AI for someone who's still learning the framework.

OpenAI ran their Codex Security tool across 1.2 million commits and found over 10,500 high-severity issues — earning 14 CVE designations for flaws discovered in projects like OpenSSH and Chromium.

And a peer-reviewed Stanford study led by Dan Boneh found something that hit close to home: developers who used AI assistants wrote significantly less secure code than those who coded without AI help. Worse, the AI-assisted developers were more likely to believe their code was secure. The tool gave them false confidence.

That's exactly what happened to me. The code looked right. The tests passed. I felt good about it. And the vulnerability shipped.

The 5-Layer Testing Strategy for AI-Generated Code

After the authentication incident, I built a layered approach. When you're working solo, no single check catches everything — but five layers together catch most of what AI gets wrong. I run through these on every feature before I consider it done.

Layer 1: Static Analysis Gates

What it catches: Style violations, type errors, known vulnerability patterns, code smells.

This is the easiest layer because it's automated. I set up static analysis to run on every push so I don't have to remember to check manually. The key is treating AI code with zero trust — assume it contains issues until the tools say otherwise.

|.github/workflows/ai-code-gate.yml
# Example CI gate for AI-generated code
name: AI Code Quality Gate

on: [pull_request]

jobs:
static-analysis:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Run ESLint with security plugin
      run: npx eslint --config .eslintrc.security.js .

    - name: Run SonarQube scan
      uses: sonarqube-scan-action@v3

    - name: Check for hardcoded secrets
      run: npx secretlint "**/*"

    - name: Dependency audit
      run: npm audit --audit-level=high

Add a secretlint or gitleaks step to your CI pipeline. AI models regularly generate code with placeholder API keys, hardcoded credentials, or example tokens that look fake but match real patterns. I've caught this three times in my own projects over the past six months.

Layer 2: Dependency and Hallucination Checks

What it catches: Phantom packages, outdated libraries, nonexistent APIs.

AI models hallucinate dependencies. They'll import a package that sounds right but doesn't exist, or reference an API method that was deprecated two years ago. This happens most often with less popular libraries where the model has limited training data — which is exactly the kind of library you end up using when you're building something niche.

Here's what I check:

  • Verify every new dependency actually exists in the registry before pushing
  • Check the last publish date — if it hasn't been updated in over a year, investigate
  • Look for typosquatting — lodash vs l0dash, express-validator vs express-validtor
  • Confirm API methods exist in the version you're actually using, not just in some version the model was trained on

Layer 3: Security-Focused Review

What it catches: Input validation gaps, authentication bypasses, injection vectors, missing error handling.

This is where my token expiration bug lived. The AI handled the complex parts — JWT signature verification, role mapping, session lookup — and skipped the basic security check. That pattern repeats constantly in AI-generated code: the impressive stuff works, the fundamental stuff is missing.

When I'm building a new feature, I force myself to slow down and check these areas:

  • Authentication and authorization — does every protected endpoint actually check permissions?
  • Input validation — is user input sanitized before it hits the database or gets rendered?
  • Error handling — do error responses leak internal details like stack traces or database schemas?
  • Rate limiting — did the AI add any throttling to public-facing endpoints?
  • Data exposure — are sensitive fields filtered from API responses?

As a QA person, I know these checks by heart. The hard part is remembering to apply them to my own code when I'm in build mode.

Layer 4: Behavioral Testing Beyond Coverage

What it catches: Logic errors that pass unit tests but fail in production.

Code coverage is the most dangerous metric for AI-generated code. The model can generate tests that execute every line but don't actually verify the right behavior. I've seen AI-generated test suites hit 95% coverage while testing nothing meaningful — asserting that functions return something, not that they return the right thing.

What I focus on instead:

  • Write tests for the behavior I expect, not the code I see. I define what the function should do before looking at how it's implemented. My QA background actually helps here — I think in terms of requirements and expected behavior, not implementation details.
  • Test the negative paths explicitly. What happens with null input? Empty strings? Integers where strings are expected? AI code is weakest at boundary conditions.
  • Test integration points. The individual functions might work perfectly. The way they connect is where AI introduces subtle bugs — especially when I've generated different parts of the system in separate sessions.

Don't let AI generate the tests for the same code it generated. You'll get tests that validate the implementation rather than the requirements. Have a different AI session generate tests from the requirements, not from the source code. For critical paths, write tests by hand — this is where your QA instincts earn their keep.

Layer 5: Duplicate Logic Detection

What it catches: Redundant implementations, inconsistent patterns, code that should use existing utilities.

AI doesn't know your codebase. Every time it generates code, it starts from scratch. I've watched it create a new date formatting function when my project already had one. I've seen it write a custom email validation regex in a file right next to an import for a validation library.

When you're building solo and generating code fast, this compounds quickly. A few weeks of AI-assisted development left me with three different implementations of the same API error handler, each slightly different, each a potential source of inconsistent behavior.

What I check now:

  • Search for similar function names before committing any AI-generated utility
  • Check if the project already has a library that handles what the new code does manually
  • Look for repeated patterns — if I see the same helper function generated twice, I stop and extract it properly

My Review Checklist for AI-Generated Code

I keep this as a pinned note. Every feature goes through it before I push:

CheckQuestion to Ask
DependenciesDo all imported packages actually exist? Are versions current?
SecretsAny hardcoded keys, tokens, or credentials — even "example" ones?
AuthDoes every protected route actually verify authentication AND authorization?
InputIs every user-facing input validated and sanitized?
ErrorsDo error responses hide internal details?
Edge casesWhat happens with null, undefined, empty string, negative numbers?
DuplicatesDoes this duplicate logic that already exists in the codebase?
TestsDo tests verify behavior from requirements, not just exercise code paths?
Negative testsAre there tests for what should fail, not just what should succeed?

What This Strategy Doesn't Catch

I want to be honest about the limits.

This system doesn't catch business logic errors that require domain knowledge. If the AI generates a pricing calculation that applies discounts in the wrong order, no static analyzer or security scanner will flag it. That requires understanding the business rules — and when you're the builder, you're the only one who knows them.

It also doesn't catch performance problems. AI-generated code often works correctly but inefficiently — unnecessary database queries inside loops, unindexed lookups, memory leaks in event handlers. I'm still learning to spot these, and it's a separate discipline entirely.

And it doesn't replace thinking. The checklist is a tool, not a substitute for understanding what the code is supposed to do. The moment I start checking boxes mechanically is the moment something slips through. I learned that the hard way with the expired token.

Frequently Asked Questions

Is AI-generated code less secure than human-written code?

Research suggests it can be. A Stanford study found that developers using AI assistants produced less secure code than those working without AI — and were more likely to overestimate their code's security. The risk isn't that AI writes uniquely bad code. It's that AI produces code that looks so polished it discourages careful review — especially when you're a solo builder with no one else checking your work.

Should I stop using AI to generate code?

No. AI code generation is what makes it possible for someone like me — a QA engineer, not a developer — to build real projects. The answer isn't to stop using it. It's to test it with the same rigor you'd apply to any code you didn't write yourself. Treat AI-generated code like code from a contractor you just hired: it might be solid, but you verify before you trust.

Can I use AI to test AI-generated code?

Yes, but with guardrails. Don't let the same AI session generate both the code and its tests — it will write tests that validate the implementation's assumptions rather than the actual requirements. Use a separate session, provide the requirements (not the source code), and review the generated tests before trusting them. For critical paths, write tests by hand.

What tools work best for scanning AI-generated code?

For static analysis: ESLint with security plugins, SonarQube, or Semgrep. For secrets detection: Gitleaks or Secretlint. For dependency auditing: npm audit, Snyk, or Dependabot. For deeper security analysis, both Anthropic's Claude Code Security and OpenAI's Codex Security are purpose-built for finding vulnerabilities that traditional tools miss.

References

Next Steps

Three things you can do this week:

  1. Add a static analysis gate to your CI pipeline that runs on every push. Start with ESLint security rules and a secrets scanner — takes 30 minutes to set up.
  2. Copy the review checklist from this post and use it on your next three AI-generated features. Adjust it based on what you find in your own projects.
  3. Try reviewing your AI-generated code without looking at the implementation first. Write down what you expect the code to do based on the requirements, then check if it actually does that. The gap between expectation and implementation is where the bugs hide.

Have you caught a sneaky bug in AI-generated code that you almost shipped? I'd like to hear what happened — reach out on the contact page or check out more on building with AI on the blog.

Continue Reading

Claude Code /btw and /voice changed how I talk to my terminal

Read more →

I Did a Live AI Demo at a QA Meetup. It Failed.

Read more →

15 Years of Finding Bugs Taught Me How to Build Software

Read more →

Stay Connected

Subscribe and get instant access to 50 free AI prompts for software testers — plus new articles on AI-powered testing, automation strategies, and quality leadership. No spam, unsubscribe anytime.