A test finds whether the code does what it was supposed to do. A review finds
whether the code does what it actually does.
What the test misses
def charge_account(amount)
balance = get_balance
if balance > amount
deduct(amount)
log("charged", amount)
else
log("declined", amount)
end
end
The test passes. Balance is sufficient, charge succeeds, log is called. All
green.
The review finds: if balance is exactly equal to amount, nothing happens. The
code is written as > not >=. The test did not catch this because the test
writer assumed the same condition as the author.
What a human finds
- A condition that is stricter than intended
- A variable name that could be clearer
- An assumption that might not be true in edge cases
- A log call in both branches that could be factored out
Tests find that the code runs. Reviews find that the code makes sense.
Why both matter
A tested untested code breaks. A reviewed tested code might be slow, might
be wrong in a way the test does not check, might be a footgun waiting to
surprise someone.
The test that misses the review
def send_email(address)
if valid_email?(address)
email_service.send(address, template)
end
end
Tests pass for valid emails and invalid emails. The review finds: what if the
email service fails? What if the template is missing? What if valid_email?
returns true for something that is not actually valid?
The review that finds the bug the test could not
A test cannot know what you did not test for. A review can ask the question:
“What happens if this breaks?” and “Are we ready for that?”
Why this matters
Code review is not about correctness. It is about resilience. A function that
works is not a function that continues to work when something changes.
The review is where you ask whether the code is ready for the future. The
test is where you confirm it works today.