Yeda AI Tips · #073

Español

Make a Flaky Test Fail Ten Times on Purpose

Flaky test? Make it fail ten times on purpose. A test that fails once in CI and passes on retry can waste a week of re-runs while the team argues about whether it's real. The fix starts with one command: run the suspect spec repeatedly on your own machine until the failure is boring and reproducible — then debug it like any other bug.

Why retries hide real bugs

A retry that turns red into green doesn't fix anything — it reclassifies it. Playwright even reports these as a separate category: a test that fails, then passes on retry, is marked flaky, not passed. Every flaky pass is a real race, timeout, or ordering bug that shipped anyway. And because CI failures are slow to iterate on (push, queue, wait 15 minutes, read logs), teams rationalize instead of reproducing: "infra was slow", "re-run it". Ten local runs in under a minute end that argument with data.

The command

Point Playwright at the one suspect file and repeat it:

npx playwright test tests/checkout.spec.ts --repeat-each=10

--repeat-each runs each matched test N times (default 1). If it's flaky, an intermittent failure that shows up 1-in-20 in CI will usually surface within seconds on your machine — now you have a deterministic loop instead of a debate.

Tighten the loop further:

FlagWhat it doesWhen to add it
--repeat-each=10Runs each test N times (default 1)Always — this is the tip
-g "adds to cart"Only runs tests matching a regexNarrow to the one test, not the file
--workers=1Single worker, no parallelismRule parallel interference in or out
--retries=0Zero retries (the default)Make sure nothing masks the failure
--trace=retain-on-failureKeeps a full trace for failed runsGet a timeline of the failing run
--headedRuns in headed browsersWatch the race happen

Compare two runs: --repeat-each=10 --workers=1 versus --repeat-each=10 at the default worker count. Fails only with parallelism? You have shared state between tests. Fails either way? The bug is inside the test or the app — usually a missing wait or a real race.

Fix the race, not the symptom

Once it fails on demand, the failure mode is usually one of three: the test asserts before the app settles (fix the wait condition, don't add a sleep), two tests share state (isolate the fixture), or the app itself has a race (congratulations — the flaky test just did its job). --trace=retain-on-failure gives you a step-by-step trace of exactly the runs that failed.

Quarantine is the last resort, not the first. If you must park a test, Playwright's test.fixme() marks it as failing and skips execution — visible in reports, unlike a deleted test — and test.fail() runs it while asserting that it does fail, so you're notified the moment the bug disappears. File the issue when you quarantine; a fixme without an owner is a deletion with extra steps.

Power user: the same move in every stack

Resources

Building an AI feature? Yeda AI designs, audits, and ships production LLM systems.

Talk to us · Read the blog