Yueser ← Back to library

AI / Coding and Debugging

Write the Smallest Failing Test

Reproduce it with the least input, not with a whole test suite

You are an engineer who is good at isolating edge cases. Write one minimal test for the bug below: 1) keep only the input and state required to trigger it, and delete everything else; 2) assert the exact expected versus actual value, not just 'should not throw'; 3) state that it must fail before the fix and pass after; 4) if it cannot be reproduced reliably, list the missing environmental conditions instead of inventing them. Put it in a single file using the existing test framework.

[bug report / relevant code / runtime]
How to use

The minimal case should survive as a regression test. A case that does not run, or passes only sometimes, is worse than none.

Good for

  • A customer reports that leaving the search box empty crashes the results page, and you want that behavior pinned before touching the code.
  • You are fixing an off-by-one in pagination and need a test that is guaranteed to fail on the current implementation.

Not for

  • You need regression coverage for the whole checkout module: this prompt produces one case, not a suite.
  • The cause is unknown and you cannot reproduce it at all: add instrumentation and logs first, then write the test.

Example

Input
function parseRange(s) {
  const [from, to] = s.split('-').map(Number);
  return { from, to };
}
// parseRange('10') returns { from: 10, to: NaN }; expected to = 10
What you get
Keep only `parseRange('10')` and assert `{ from: 10, to: 10 }`; leave out the UI and network layers entirely. Run it against the current code and paste the failure (`to: NaN`) so the test is proven to catch the bug. If the product rule is that a bare value is invalid, rename the test and assert a thrown error instead — do not leave both semantics ambiguous.

Common mistakes

  • Turning the full checkout flow into the 'minimal' test: when it fails, you cannot tell the target bug from environment flakiness.
  • Asserting only that nothing throws: an implementation that returns null still passes, and the bug is not pinned at all.

Try tweaking it like this

  • Parameterize it over three boundary values (empty string, zero, negative) and you cover the neighbors without a second file.
  • Replace 'must fail before the fix' with 'paste the current failure output' and you get evidence rather than a promise.

More in this topic