</>

Technology

Playwright

Difficulty

Advanced

Interview Question

What are performance optimization techniques for large Playwright test suites?

Answer

Playwright Performance Optimization

1. Maximize Parallel Execution

TypeScript
// playwright.config.ts
export default defineConfig({
  fullyParallel: true,     // All tests parallel
  workers: process.env.CI
    ? 4
    : Math.floor(require('os').cpus().length / 2), // Half CPU count locally
});

2. Reuse Authentication State (Biggest Win)

Without optimization: 500 tests × login (5s) = 41 minutes just on logins
TypeScript
// Login ONCE, reuse for all tests
projects: [
  { name: 'setup', testMatch: '*.setup.ts' },
  {
    name: 'e2e',
    use: { storageState: '.auth/user.json' },
    dependencies: ['setup'],
  },
],
With storageState: login cost = 5 seconds total (not 5s × 500 tests)

3. Use API for Test Data Setup (Not UI)

TypeScript
// BAD — UI-based setup is slow
test.beforeEach(async ({ page }) => {
  await page.goto('/products/new');
  await page.fill('#name', 'Test Product');
  await page.fill('#price', '99.99');
  await page.click('#save');
  // 3-5 seconds per test
});

// GOOD — API setup is fast
test.beforeEach(async ({ request }) => {
  await request.post('/api/products', {
    data: { name: 'Test Product', price: 99.99 },
    headers: { Authorization: `Bearer ${process.env.ADMIN_TOKEN}` },
  });
  // 200ms per test
});

4. Block Unnecessary Network Requests

TypeScript
// Block analytics, ads, and images to speed up page load
await page.route('**/*.{png,jpg,jpeg,gif,webp,svg}', r => r.abort());
await page.route('**/google-analytics.com/**', r => r.abort());
await page.route('**/hotjar.com/**', r => r.abort());
await page.route('**/facebook.com/**', r => r.abort());

5. Use networkidle Sparingly

TypeScript
// BAD — networkidle waits for ALL network activity (500ms of silence)
await page.goto('/products', { waitUntil: 'networkidle' }); // Slow

// GOOD — wait for specific element instead
await page.goto('/products');
await page.locator('.product-card').first().waitFor();

6. Avoid page.waitForTimeout()

TypeScript
// BAD — arbitrary sleep
await page.waitForTimeout(3000);

// GOOD — wait for the actual thing you need
await page.locator('.modal').waitFor({ state: 'hidden' });
await expect(page.locator('.data-loaded')).toBeVisible();

7. Efficient Test Data Strategy

TypeScript
// Use unique data per test to avoid cleanup conflicts
const uniqueEmail = `user-${Date.now()}-${Math.random().toString(36).slice(2)}@test.com`;

// Use a test-specific database schema/namespace
process.env.DB_SCHEMA = `test_${testInfo.workerIndex}`;

8. Shard in CI

YAML
strategy:
  matrix:
    shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
    shardTotal: [8]

8 shards × 4 workers = 32 tests running simultaneously.

Performance Checklist

OptimizationExpected Speedup
fullyParallel: true2-4x
storageState auth reuse3-5x
API setup vs UI setup5-10x per test
Block unnecessary assets20-40% page load
Sharding (8 machines)8x
Minimize networkidle10-30% per navigation

Follow AutomateQA

Related Topics