Retry Mechanism in Playwright



Retry Mechanism in Playwright

Retries in Playwright help reduce flaky test failures caused by temporary issues such as network delays, slow page loads, or timing problems. If a test fails, Playwright can automatically rerun it before marking it as failed.

  1. Configure Retries Globally

In playwright.config.ts:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

retries: 2,

});

Behavior:

  • 0 → No retries (default)
  • 1 → Retry once after failure
  • 2 → Retry twice after failure

If the test passes on a retry, Playwright marks it as flaky.

  1. Configure Retries for CI Only

A common practice is to retry only in CI.

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

retries: process.env.CI ? 2 : 0,

});

  • Local execution → No retries
  • CI execution → Retry twice
  1. Retry Individual Tests

You can override retries for a specific test or suite.

import { test, expect } from ‘@playwright/test’;

test.describe.configure({ retries: 3 });

test(‘Login Test’, async ({ page }) => {

await page.goto(‘https://example.com’);

await expect(page).toHaveTitle(/Example/);

});

  1. Detect Retry Number

Playwright provides retry information through testInfo.

import { test, expect } from ‘@playwright/test’;

test(‘Retry Example’, async ({ page }, testInfo) => {

console.log(`Retry Count: ${testInfo.retry}`);

await page.goto(‘https://example.com’);

expect(await page.title()).toContain(‘Example’);

});

Output:

Retry Count: 0

If it fails:

Retry Count: 1

Second retry:

Retry Count: 2

  1. Execute Some Code Only During Retry

test(‘Retry Demo’, async ({ page }, testInfo) => {

if (testInfo.retry > 0) {

console.log(“Running after retry…”);

}

await page.goto(‘https://example.com’);

});

Useful for:

  • Taking extra logs
  • Clearing cache
  • Resetting test data
  1. Capture Screenshot Only on Retry

test(‘Retry Screenshot’, async ({ page }, testInfo) => {

if (testInfo.retry > 0) {

await page.screenshot({

path: `retry-${testInfo.retry}.png`

});

}

await page.goto(‘https://example.com’);

});

  1. Retry Failed API Calls (Custom Logic)

Retries apply to tests, not individual API requests. You can implement request retries yourself.

async function getUser(request) {

for (let i = 1; i <= 3; i++) {

const response = await request.get(‘/users’);

if (response.ok()) {

return response;

}

console.log(`Attempt ${i} failed`);

}

throw new Error(“API Failed”);

}

  1. Retry Clicking an Element

Normally, Playwright automatically retries actions until the action timeout expires.

await page.locator(‘#submit’).click();

Playwright waits until the element is:

  • Visible
  • Stable
  • Enabled
  • Receives events

So you usually don’t need manual retry logic for clicks.

  1. Retry Assertions

Playwright assertions automatically retry until the expectation timeout.

await expect(page.locator(‘.success’))

.toHaveText(‘Order Placed’);

This keeps checking until:

  • Text matches, or
  • Timeout is reached.
  1. Retry Entire Test Example

import { test, expect } from ‘@playwright/test’;

test.describe.configure({ retries: 2 });

test(‘Login Example’, async ({ page }, testInfo) => {

console.log(`Retry Number: ${testInfo.retry}`);

await page.goto(‘https://opensource-demo.orangehrmlive.com/’);

await page.locator(‘input[name=”username”]’).fill(‘Admin’);

await page.locator(‘input[name=”password”]’).fill(‘admin123’);

await page.locator(‘button[type=”submit”]’).click();

await expect(page.locator(‘h6’)).toHaveText(‘Dashboard’);

});

Test Status After Retries

First Attempt Retry Result Final Status
Pass Passed
Fail Pass Flaky
Fail Fail Failed
Fail Fail Failed after all retries

Best Practices

  • ✅ Use retries for intermittent (flaky) failures, not to hide real defects.
  • ✅ Keep retries low (1–2 attempts is usually enough).
  • ✅ Enable retries mainly in CI environments.
  • ✅ Investigate and fix flaky tests instead of relying on retries.
  • ✅ Use testInfo.retry to collect additional diagnostics (screenshots, logs, traces) on retry attempts.
  • ✅ Combine retries with Playwright’s automatic waiting and retrying assertions rather than adding unnecessary manual retry loops.

 

Tags:
Leave a comment

Your email address will not be published. Required fields are marked *

Subscribe now

Receive weekly newsletter with educational materials, new courses, most popular posts, popular books and much more!