‹ Learn agentic development

4. Reviewers and test-first fixes

In short

  • Builders test what they thought of; reviewers with a different question find the rest.
  • Four lenses (security, isolation, contract, operations) found 14 real problems in code with 325 passing tests.
  • Rule: reproduce every finding with a failing test first. No failing test, no fix.
On this page

Passing tests are not enough

After integration the backend had 325 passing tests on SQLite and PostgreSQL. Four reviewers then found 14 real problems. Every one of them was invisible to the tests the builders had written, because the builders hadn’t thought of those situations.

Four lenses

Each reviewer got one question to ask of the whole codebase, read-only:

LensThe question
SecurityTokens, passwords, rate limits, uploads, error messages, mass assignment
Isolation and privacyCan user B see, change, export or attach to anything of user A, through any endpoint? Does deleting really delete files?
ContractDoes every endpoint match the spec on both databases? Races in “create if not exists”?
OperationsDoes the README work from scratch? Docker, migrations twice, cleanup, version pins?

A reviewer with one sharp question goes deeper than one asked to “review everything”.

What they found

SeverityFindingWhy the tests missed it
highA future database migration on SQLite could silently delete users’ nights (foreign keys are enforced inside a migration transaction)No migration has rebuilt a table yet
mediumThe protection against password guessing could be bypassed by sending many attempts at the same momentTests send one request at a time
mediumWith the default Docker settings, every visitor would share one rate-limit bucket behind a proxyDocker wasn’t running during the build
mediumA NUL character in a text field crashed PostgreSQL (fine on SQLite)Nobody types NUL characters in tests
mediumNaN or Infinity in event details: crash on PostgreSQL, silently changed on SQLiteSame
mediumTimestamps near year 1 or 9999 caused a server errorSame
mediumRunning the tests with the wrong setting in your shell could drop every table of a real databaseThe builder’s own shell was always clean
mediumAn .env copied from the example but not filled in crashed the appThe builder never copied the example
mediumOn Windows, a recording file that was open during deletion stayed on diskFiles are rarely open during tests
lowTwo people registering at the same moment on an empty server could both become adminSequential tests
lowTwo admins demoting each other at the same moment caused a deadlockSame
lowReusing a logged-out refresh token didn’t end the other sessionsSpec wording read differently
lowMinimum versions in requirements.txt allowed versions the code couldn’t importBuilders had newer versions installed

Notice the pattern: concurrency, unusual input, the other database, and “a fresh machine”. Those are the four places to look in any review.

The rule: a failing test first

The fixer got one instruction that mattered most: for each finding, first reproduce it with a test. If the test fails, fix the code until it passes and keep the test. If you can’t reproduce it, don’t change code; mark it rejected with the reason.

Why:

  • It proves the problem is real. Reviewers can be wrong; a failing test can’t.
  • It proves the fix works, not just that the code changed.
  • It keeps the problem from coming back: the test stays in the suite. For the race conditions, the tests send many requests in parallel threads and check that exactly one admin exists.

All 14 findings were reproduced and fixed; none were rejected. Final count: 381 tests on SQLite, 380 on PostgreSQL.