When the test agrees with the bug
A test suite can become internally coherent while its model drifts from production, leaving green evidence for a world the software never inhabited.
Verification is only as strong as its ability to disagree with the system it tests. That is easy to forget because agreement looks so much like evidence. The implementation returns what the fixture predicts.
The fixture returns what the implementation predicts. The mock accepts the expected input. The success path keeps moving. One assertion becomes ten, ten become fifty, and somewhere along the way agreement gets promoted into evidence.
The trouble is that green has a way of making people polite. Nobody wants to cross-examine fifty passing tests. The suite has earned its green. It has done its job.
But pressure testing requires difference. If every part of the verification inherited the same assumptions that made the implementation coherent, agreement may prove only that one model has learned how to repeat itself.
During an instance, one production path carried fifty green integration tests. Those tests exercised record creation, evidence linking, event delivery, status changes, and approval behavior. They did not merely check that a function had been called. They appeared to verify the feature all the way through.
The feature had never worked in production.
Two representations, one untested boundary
The failure began with an ordinary boundary. On one side, storage held a raw representation. On the other, the application received a normalized representation produced by the data layer. Both described the same setting, but they were not interchangeable.
Production crossed that boundary. The data layer translated the stored value and returned the application-facing form.
The tests did not. Their fixture supplied the raw storage-facing form directly to the application. That happened to be the form the broken implementation expected.
Inside the test world, everything aligned. The fixture matched the implementation. The implementation found the setting. Every later action became reachable. Records were created. Evidence was linked. Events were emitted. Statuses changed. The assertions were not individually dishonest; they all followed correctly from the world the fixture had supplied.
Production supplied a different world: the one produced by the real boundary. The application received the normalized form, the broken access failed, and the flow stopped before any of the behavior downstream could begin.
Fifty tests had verified what happened after a gate that production could not cross.
The test rehearsed a world the software never inhabited.
This is where test count becomes misleading. Every new downstream assertion made the suite more persuasive without making its starting assumption more independent. The suite accumulated confidence on top of a premise it was structurally unable to challenge.
Otherwise, the implementation is asserting itself twice.
Agreement is not independence
A test does not become an independent source of evidence because it lives in another file, uses another object, or runs in another process. Independence depends on where its expectations came from and what boundary it is capable of making visible.
Consider a compatibility check meant to prove that a migration preserved every method in an interface. The test compares the methods on the migrated object with the methods exposed by the composed public surface. It passes. The sets are identical.
But the public surface holds the exact same object reference. If a method disappears from the migrated object, it disappears from both sides of the comparison at once. The assertion still passes. It can prove that the public name points at the intended object; it cannot prove that the object preserved its methods.
That distinction is not pedantry. It is the difference between wiring evidence and preservation evidence. The test may be useful, but its authority has a ceiling.
The same failure appears when a tolerant mock ignores an input that the real implementation honors, when an offline fixture repeats an assumed provider response shape, when a hand-built descriptor stands in for a different production registry, or when a test exits before reaching the assertion named in its title. The local mechanisms differ. The shared condition is that verification and implementation agree without encountering a constraint capable of separating them.
Mock Truth
The dangerous result is not simply a bad mock. Mocks are useful. Fixtures are necessary. Controlled environments make focused verification possible. The danger arrives when a bounded test model becomes persuasive enough to inherit the authority of system evidence, then continues to hold that authority after the contract it represents has moved.
Mock Truth is an outcome, not an accusation about intent. It often begins with a reasonable model. A fixture captures the boundary as it is understood today. A mock removes an expensive dependency. A compatibility check protects a migration. Downstream tests build on that representation because using the shared fixture is consistent and efficient.
Then one side changes—or was misunderstood from the beginning. The real adapter normalizes a value. The provider returns a different field shape. A production registry uses another implementation. An ambient file changes the conditions around the test runner. Nothing forces the verification model to meet the changed boundary, so it remains internally consistent.
That consistency is what gives Mock Truth its force. A visibly broken test attracts suspicion. A coherent model with hundreds of green dependents attracts trust. When production later fails somewhere downstream, the green suite directs investigation away from the boundary where the two accounts first separated.
Mock Truth can drift without ever becoming test failure.
Production is another model
The answer is not to declare production infallible. A mock may encode the intended contract more faithfully than a broken production adapter. A live response may expose current behavior while violating a documented promise. A snapshot can preserve a deliberate compatibility boundary that a refactor accidentally breaks.
No test reaches unmediated reality. Specifications, schemas, fixtures, live responses, integration environments, and production observations are all models. They carry histories and blind spots of their own.
The point of disagreement is therefore not to crown whichever model looks more real. It is to stop silent agreement from being treated as a verdict. When two differently sourced models collide, the conflict becomes visible. Contract ownership, current intent, and provenance can then decide which account needs repair.
Confidence comes from differently sourced models colliding, not from declaring production truth.
FIG 01 · EVIDENCE DRIFT
Where agreement stops being evidence
Two models begin from one promise. Only one is forced through the real boundary.
Production model
- 01The promised contract
- 02The real boundary transforms it
- 03Production behavior answers back
Verification model
- 01The same promised contract
- 02A cooperative representation replaces the boundary
- 03Green assertions accumulate authority
INTERVENTION · THE DISAGREEMENT TEST
Force the models back into contact.
- 01Name the claim and its evidence ceiling.
- 02Trace provenance and shared ancestry.
- 03Locate the boundary their agreement avoided.
- 04Force a collision and resolve what the disagreement means.
- 05Record scoped confidence and preserve a future collision point.
The Disagreement Test
The first question is not whether the suite is green. It is not even whether a test looks thorough. The first question is: what fact in this verification can disagree with the implementation?
If the expected value was copied from the implementation, both sides may change together. If the fixture represents the consumer’s preferred shape rather than the boundary’s contract, the test may protect the mistake. If a mock removes the exact constraint whose behavior is being claimed, the test may verify a mechanism while borrowing authority for an outcome it never observed.
The evidence itself needs testing.
Disagreement reveals divergence. It does not decide the case. The test may be wrong. Production may be wrong. The specification may be stale. The contract may never have had an owner. The method earns its value by making those conditions impossible to hide behind undisturbed agreement.
Five phases, eleven obligations
1. Name the claim and its evidence ceiling.
- Name what the test claims to prove: wiring, local mechanism, boundary translation, contract compliance, composition, or a user-visible outcome.
- State what this class of test can prove and what it cannot. Do this before the number of assertions begins negotiating for more authority.
2. Trace provenance and shared ancestry.
- Trace where the implementation input, fixture, mock, expected value, and invariant came from: specification, schema, implementation detail, production observation, or another test.
- Find shared ancestry. If the implementation and its expectation inherited the same assumption, treat them as one source regardless of how many files repeat it.
3. Locate the boundary their agreement avoided.
- Identify the mapping, serialization, adapter, storage layer, transport, lifecycle transition, registry, or environment that the verification replaced with a cooperative representation.
- Introduce a differently sourced constraint: the real boundary, an explicit current contract, an invariant, a recorded live shape, or an alternate implementation path.
- Predict the red condition. Name the plausible drift that must make the verification fail. If nothing can turn it red, reduce the claim or redesign the evidence.
4. Force the models to collide.
- Bring the two accounts into contact at the boundary where they are supposed to agree. Do not declare either one authoritative in advance.
- Resolve the disagreement by provenance and ownership. Repair the model that violates a current explicit contract. If behavior changed intentionally, revise the contract before teaching both sides the new answer. If ownership is ambiguous, withhold the confidence that depended on it.
5. Preserve honestly scoped confidence.
- Record what the evidence now proves. Wiring remains wiring. Boundary translation remains boundary translation. An integrated outcome requires an integrated path.
- Keep a future collision point and name what must trigger its review. Models will evolve. The protection is not permanent agreement; it is preventing them from drifting indefinitely without contact.
This is not a demand for every unit test to boot production. It is a demand that the authority granted to evidence match the boundary it actually encounters.
The useful mock and the honest claim
Cooperative mocks remain useful for local control flow. A same-reference comparison can prove composition wiring. A fixture can make error paths deterministic. A fake transport can test normalization without spending money or depending on a network.
The failure begins when those instruments inherit claims they are structurally incapable of disproving.
A local mechanism test may deserve a fast, cooperative world. It should say that it proves the mechanism. A boundary contract deserves at least one check sourced from the other side of that boundary. A live integration deserves a smoke test through the real transport. A production-shaped workflow deserves evidence that the packaged artifact, registry, environment, and lifecycle participate in the path being trusted.
Different risks need different collision points. The convention is proportional, not maximal: find the claim carrying release confidence, then make sure something inside its evidence can answer no.
Every green light has a jurisdiction
The most dangerous suite is not the small one. It is the persuasive one whose authority has grown beyond the jurisdiction of its models.
Green means that the observed account remained coherent under the constraints the test supplied. That can be valuable. It can also be much less than the surrounding workflow needs it to mean.
Systems engineering requires knowing the difference.
Pressure testing a system means introducing a constraint capable of exposing what its familiar supports concealed. The same obligation applies to the evidence used to trust that system. Salt tests the supports. Disagreement tests the proof.
Every test should claim only the authority its model has earned.
More from this theme
Fresh eyes need a different bias
Several reviewers can share one blind spot when they inherit the same path. Review independence comes from introducing a different path, then testing what it finds against the code.
The experiment is still yours
AI can help produce the work. It cannot own the hypothesis, the architecture, the risk, or the lifecycle.