← Back to Tutorials

16. Test Retries & Parallel Execution

Retries

// Config-level retries
export default defineConfig({
  retries: 2,  // retry failed tests up to 2 times
  // OR conditional
  retries: process.env.CI ? 3 : 1,
});

// Test-level retry (overrides config)
test('flakey test', async ({ page }) => {
  test.info().annotations.push({
    type: 'issue',
    description: 'https://github.com/org/repo/issues/123',
  });
});

Parallel Execution

// Config-level
export default defineConfig({
  fullyParallel: true,     // run all tests in parallel across files
  workers: 4,              // number of parallel workers
  // workers: process.env.CI ? 2 : undefined,
});

// File-level (in test file)
import { test } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });  // 'parallel' | 'serial'

Serial Execution

// When tests depend on each other
test.describe.configure({ mode: 'serial' });

test('step 1 - create user', async ({ page }) => { /* ... */ });
test('step 2 - login as user', async ({ page }) => { /* ... */ });
test('step 3 - delete user', async ({ page }) => { /* ... */ });

// If step 1 fails, steps 2 and 3 are skipped

Sharding (CI)

// Run across multiple CI machines
# Machine 1
npx playwright test --shard=1/4

# Machine 2
npx playwright test --shard=2/4

# Machine 3
npx playwright test --shard=3/4

# Machine 4
npx playwright test --shard=4/4

Best Practices

✏️ Exercise: Configure retries=2 and fullyParallel=true. Run a test suite with 10 tests. Observe the parallel execution speed. Intentionally fail one test and verify it retries.