MATTHEWLAB
Software engineering

The test was green before the fix, too.

A unique database row can hide repeated attempts and repeated side effects. Choose the observation that matches the bug.

A magnifying glass examines repeated rows of colored test markers on a board.

Call a function twice. One notification remains in the database. A duplicate-prevention test turns green. It is tempting to stop there, particularly when the change itself looks small.

But suppose the same test passes after removing the new guard. What did it actually establish?

Take a constructed notification service. The application checks whether a notification exists, while a unique database constraint independently rejects a second row. A test that only counts rows observes the database's final state. It may say nothing about whether the application attempted the second operation.

A final state can hide an extra action

The distinction becomes visible when delivery happens before the rejected write. The database can contain one row while two messages were sent. This is a hypothetical failure sequence, not a report of a production incident.

RequirementUseful observation
No duplicate stored recordsFinal records and enforced uniqueness
No repeated creation attemptAttempts recorded by a safe test double
No duplicate deliveryDelivery calls and their identities

These are different requirements. A storage constraint is valuable, but it should not receive credit for protecting an unrelated side effect. I would keep the constraint and isolate the application behavior in a test environment. Removing a production safeguard to make a test fail would be a rather expensive way to learn this.

There is a tradeoff. Asserting every internal call makes tests brittle when the implementation changes. The observation should therefore follow an external requirement: one delivery, no second charge, or no additional creation attempt when that attempt itself matters. It should not follow whichever helper happens to be easiest to spy on.

Make the old behavior fail for the right reason

For a regression test, I want to see the failing input exercise the old behavior and then pass with the fix. An import error or a broken fixture is not the red part of that demonstration. The failure should explain the user-visible problem being repaired.

A sequential two-call test also cannot establish safety under concurrency. Two requests that both inspect an empty state before either writes need a separate scenario. Naming a test narrowly is useful: it stops a small successful check from quietly becoming a much larger claim.

Before adding another test, I would remove the fix locally and ask whether the current test notices. If it stays green, the next task is to understand that result. More green runs will not answer the question.

한국어 글: 고치기 전에도 통과하는 테스트라면