The Failed Test: Debugging Automation Like a Senior · Lesson 4 of 6 · Bonus module

Flaky or Broken: Prove It With a Number

"It's just flaky" is a claim without data. Fifty runs turns it into a number — and the number decides what happens next.

By Shahriyar · Updated

Measure it

▸ Fifty runs, one number
pass=0; fail=0
for i in {1..50}; do
  pytest -q tests/test_checkout.py::test_guest_checkout >/dev/null 2>&1 \
    && pass=$((pass+1)) || fail=$((fail+1))
done
echo "passed $pass / failed $fail"
# (pytest-repeat does the same: pytest --count=50 -x <test>)

Why a "small" rate is a big deal

One test failing 0.5% of the time sounds harmless. Two hundred like it fail a build most days, and the team learns to click re-run without reading.

That habit — not the race — is what kills automation. Google has published that most of its retried test failures are flakiness, not real regressions. Once a team expects that, a real red gets ignored with the rest.

sleep(2) is how frameworks die

▸ The nap vs the condition
# bad — hides the race, taxes every run forever, still fails on a slow day
time.sleep(2)
page.click("#place-order")

# good — waits exactly as long as the condition takes, and fails honestly
expect(page.locator("#cart-total")).to_have_text("$41.98")
page.click("#place-order")

The nap doesn't fix the race — it moves it. And it charges two seconds, times every copied test, times every run, forever.

Quarantine, with a paper trail

A test measured flaky gets marked, ticketed and owned — the same day. The mark keeps the build honest; the ticket keeps the coverage loss visible.

Grounded in pytest-repeat and published flaky-test research from Google and Microsoft

All lessons in The Failed Test: Debugging Automation Like a Senior

  1. The Four Questions That Sort Any Failure
  2. Reading the Traceback Like a Senior
  3. Shrinking the Search Space
  4. Flaky or Broken: Prove It With a Number
  5. It Only Fails in CI
  6. The Write-Up: Product Bug or Test Bug