Taming Flaky UI Tests with Mocha's Built‑In Retry Feature
Mocha's native retry feature lets you automatically re‑run flaky UI tests up to a configurable number of times, reporting the attempt count so you can see exactly how often a test needed a second chance.
03 Jul 2026, 15:43 UTC

The problem: flaky UI tests slow down CI
UI tests that interact with a browser or a headless driver often fail intermittently due to timing, network jitter, or race conditions in the application under test. When a test fails once in a hundred runs, the pipeline turns red and developers waste time re‑running the suite manually.
Mocha's retry mechanism in a nutshell
Since version 6.0.0 Mocha ships a native retry API. You can tell Mocha to re‑execute a failed test up to n times before finally marking it as failed. The feature works for synchronous tests, callbacks, promises, and async/await without any code changes.
- Global:
mocha --retries 2 - Per suite:
describe('flaky', function(){ this.retries(2); … }) - Per test:
it('should load', function(){ this.retries(2); … })
When a test eventually passes, Mocha reports the attempt count (e.g. ✓ should load (retry 1)), giving immediate visibility into how often the test retries.
Worked example: a test that passes 1 out of 3 runs
// test/flaky-ui.test.js
const { expect } = require('chai');
it('loads the dashboard', function () {
this.retries(2); // retry up to two additional times
// Simulate a flaky condition: succeed only on the third call
if (!this.test._flakyCounter) this.test._flakyCounter = 0;
this.test._flakyCounter += 1;
if (this.test._flakyCounter < 3) {
throw new Error('Transient UI glitch');
}
expect(true).to.be.true;
});
Run it with:
mocha --retries 2 test/flaky-ui.test.js
Expected console output (illustrative, not a captured run):
1) loads the dashboard
Error: Transient UI glitch
2) loads the dashboard
Error: Transient UI glitch
✓ loads the dashboard (retry 2)
The final line shows the test passed on the third attempt and Mocha logged the retry count.
Trade‑offs and limitations
- Hooks are not retried.
beforeEach/afterEachrun only once per test invocation. If flakiness originates in setup, retries will not help. - Masking real regressions. Over‑reliance on retries can hide a genuine bug that only appears under certain conditions. Treat retries as a temporary safety net, not a fix.
- Increased CI time. Each retry adds execution time; keep the retry count low (1‑2) for UI suites.
Actionable next steps
- Verify Mocha version:
mocha --version(must be ≥ 6.0.0). - Add
this.retries(2)only to the specific UI tests that exhibit flakiness. - Enable a CI job that records retry counts (e.g., parse Mocha's JSON reporter) and alerts when a test retries more than a threshold.
- Schedule a root‑cause investigation for any test that retries repeatedly; fix the underlying timing or state issue and then remove the retry.
Used wisely, Mocha's built‑in retry keeps the pipeline green while you eliminate the real sources of instability.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.