← Back to libraryQuestion 177 of 273
🎭PlaywrightIntermediate

Retries, Timeouts & Flaky-Test Strategy

📌 Definition:

Playwright distinguishes several timeouts (test, action/navigation, expect) and supports automatic retries. Used well, retries surface flaky tests (marked 'flaky' when they pass on retry) without hiding real failures; used badly, they mask bugs.

📖 Detailed Explanation:

There are three timeout layers: the overall test timeout (default 30s), per-action/navigation timeouts, and the separate expect assertion timeout (default 5s). Configure retries in playwright.config, typically retries: 2 on CI and 0 locally. When a test fails then passes on retry, Playwright reports it as 'flaky' rather than passed — a crucial signal you should track and fix, not celebrate. Retries paired with trace: 'on-first-retry' capture a full trace of the first failure for diagnosis without slowing green runs. The strategy: retries are a safety net for genuinely non-deterministic conditions (network jitter), not a substitute for fixing races. A rising flaky count means real problems (bad waits, shared state) that need addressing.

🔑 Key Points:
  • Three timeouts: test (30s), action/navigation, and expect (5s) — tune independently
  • retries: 2 on CI, 0 locally is a common default
  • A pass-on-retry is reported as 'flaky' — a signal to fix, not to ignore
  • trace:'on-first-retry' captures the first failure cheaply for diagnosis
  • Retries mitigate true non-determinism; they must not mask real bugs or bad waits
🌍 Real-World Example:

CI shows 12 tests as 'flaky' over a week. Instead of shrugging because they eventually pass, the team opens each first-retry trace, finds most are the same overlay/network race, fixes the waits, and the flaky count drops to near zero — retries did their job as a diagnostic, not a crutch.

📎 Code Example:
// playwright.config.ts (excerpt)
export default defineConfig({
  timeout: 30_000,                 // per test
  expect: { timeout: 5_000 },      // per web-first assertion
  retries: process.env.CI ? 2 : 0,
  use: {
    actionTimeout: 10_000,         // per action (click/fill/...)
    navigationTimeout: 15_000,     // per navigation
    trace: 'on-first-retry',       // capture the first failure only
  },
});

// Override a single slow test's budget
// test('big report', async ({ page }) => { /* ... */ });
// test.setTimeout(120_000);
🎯 Scenario-Based Interview Question:

Scenario: A manager wants retries: 5 on CI 'so the pipeline stays green'. The flaky dashboard is ignored. Why is this dangerous, and what policy do you propose instead?