All Modules Why Test Test Types TDD With AI Don't Trust Blindly عربي

Testing AI-Generated Code

The first real safety net for "works once" — so the next AI change can't silently break the last one.

Module 6 · Turn acceptance criteria into automated tests.

Intermediate Testing Includes Lab ~50 min

What You'll Learn

  • Why tests matter most when an AI is changing your code constantly
  • The test types you actually need for a small app: unit and API integration
  • TDD-with-AI: turn acceptance criteria into tests, then make them pass
  • Why coverage isn't correctness — and how to read the AI's tests critically
  • Hands-on lab: add a test runner and cover M1–M3, catching a deliberate bug

Prerequisites: Module 5 — a working snippet vault (create, list, search, delete).

Why Tests, Why Now

Failure mode #1 from Module 1 was "works once": the demo runs, but the next change silently breaks something and nobody notices. When an AI is rewriting your code many times a day, that risk multiplies. Automated tests are the fix — they re-check your acceptance criteria in seconds, every time.

Without testsWith tests
You click through the app hoping nothing brokeOne command confirms every feature still works
Regressions ship silentlyA broken feature fails the build loudly
"Done" is a vibe"Done" = the acceptance-criteria tests pass

Your spec already wrote the tests

Remember the acceptance criteria you wrote in Module 3? "Empty title is rejected", "search is case-insensitive"… each one is a test waiting to be written. Tests are just your spec, made executable.

The Tests You Actually Need

Don't drown in test theory. For a small app, two kinds carry the weight:

TypeChecksExample for the vault
UnitOne small function in isolationThe search filter returns matches case-insensitively
API integrationAn endpoint end to endPOST /snippets creates and returns a snippet; empty title is rejected

Skip the pyramid arguments

You'll hear about unit vs integration vs end-to-end ratios. For now: write a test for every acceptance criterion at the level that's cheapest to check. Mostly that's API integration tests for the endpoints and a couple of unit tests for tricky logic.

TDD With an AI

Test-Driven Development pairs beautifully with an assistant: write the test first (from an acceptance criterion), watch it fail, then have the AI make it pass. The failing test is a crystal-clear target the assistant can't wander away from.

1. Pick an acceptance criterion → "empty title is rejected with 400" 2. Write (or have AI write) a test → expect POST {title:""} to return 400 3. Run it → it fails (red) 4. Ask the AI to implement until it passes → green 5. Commit. Next criterion.

Prefer test-after? That's fine too — just don't skip it. The rule is simply: every acceptance criterion ends up with a test, whether you write it before or after the code.

A great prompt

"Write API integration tests for the acceptance criteria of stories M1–M3 in SPEC.md. One test per criterion, clear names. Don't change app code — just the tests." Then you review them, run them, and only then let it fix failures.

Never Trust Blindly

AI-written tests have a trap: an assistant can write a test that always passes, or that tests the wrong thing, and proudly report "all green." Green is only meaningful if the tests are real.

TrapGuard
Test asserts nothing meaningfulRead each test — does it actually check the behavior?
100% coverage, 0% confidenceCoverage measures lines run, not correctness. Don't chase the number.
Tests pass because they mock everythingKeep at least some tests hitting the real endpoint.

The proof: break it on purpose

The only way to trust a test is to see it fail for the right reason. Temporarily introduce a bug (e.g. accept an empty title) and confirm a test goes red. If nothing fails, your test wasn't testing anything.

Practical Lab: Cover M1–M3 With Tests

You'll add a test runner, turn your acceptance criteria into automated tests, and prove they work by catching a deliberate bug.

What you need

Your snippet-vault repo from Module 5 with M1–M3 working.

1

Branch and add a test runner

git checkout -b feature/tests

Ask the assistant to set up a test runner in api/ (Jest or Vitest with Supertest for HTTP). Review the config diff; commit it.

2

Turn acceptance criteria into tests

Write API integration tests for the acceptance criteria of M1–M3 in SPEC.md: create returns the snippet, empty title → 400, list returns all, search filters case-insensitively, delete removes one. One test per criterion, clear names. Tests only — don't touch app code.

Read every test. Does each assert the real behavior?

3

Run them green

cd api && npm test

If any fail, decide: is the test wrong, or the code? Fix the right one. Commit when green.

4

Prove a test bites

Temporarily let the create endpoint accept an empty title. Run the tests — the "empty title rejected" test should go red. If it doesn't, your test is fake; fix it. Then revert the bug.

5

Merge and reflect

git add . git commit -m "Add tests for M1–M3 acceptance criteria" git checkout main && git merge feature/tests

In REFLECTION.md: which test caught the deliberate bug, and did any AI-written test turn out to assert nothing? Commit it.

What to hand in

Your snippet-vault repo. Self-check:

  • npm test runs and passes in api/
  • There's a test for each M1–M3 acceptance criterion
  • You confirmed a test goes red when you break the code
  • REFLECTION.md notes the bug a test caught

Mini Glossary

TermPlain meaning
Unit testChecks one small function in isolation.
Integration testChecks parts working together — e.g. a whole API endpoint.
TDDWrite the failing test first, then code until it passes.
RegressionA previously working feature that a new change broke.
CoverageThe % of code lines your tests run — useful, but not proof of correctness.

Recap & What's Next

You now have

A test suite that turns your acceptance criteria into an executable safety net — run in one command, proven to catch a real bug. "Works once" is now "keeps working."

Next up: Module 7 — Quality Gates & Security. Tests catch broken behavior; now we add the gates that catch bad style and dangerous security holes — linting, secret scanning, and validation — before they reach main.

Testing AI-Generated Code

Objectives Why Test Test Types TDD With AI Don't Trust Blindly Practical Lab Glossary Recap