Skip to content

Playwright Best Practices

Reliable Playwright suites share common habits: user-facing locators, isolated browser contexts, API mocking for deterministic data, reused auth via storageState, and traces enabled on retry. This lesson consolidates the patterns used across mature teams.

The Reliable Test Stack

Locate with getByRole, getByLabel, and getByTestId — in that priority order. Interact only after visibility is guaranteed by auto-waiting, and assert with web-first expect() matchers instead of manual polling.

Stub backend responses with page.route() so UI tests validate presentation logic without depending on live API availability. Save authentication once with globalSetup + storageState for suites that mostly test post-login flows.

test.use({ storageState: 'playwright/.auth/admin.json' });

test.beforeEach(async ({ page }) => {
  await page.route('**/api/orders', route =>
    route.fulfill({ json: [{ id: 1, status: 'shipped' }] })
  );
});

Combine auth reuse and network stubs for fast, deterministic suites.

Best Practice Checklist

✓ getByRole / getByLabel locators
✓ await on every Playwright call
✓ page.route for API-dependent UI
✓ storageState for auth
✓ trace: 'on-first-retry'
✗ page.waitForTimeout()
  • One assertion focus per test when possible — easier failure diagnosis.
  • Independent tests: no shared mutable state between test() blocks.
  • Tag smoke tests with @smoke for fast PR gates.
  • Keep E2E count small; push permutations to component or API tests.

Best Practices Summary

Do this, not that.

Do Avoid
getByRole() CSS/XPath indexes
expect() waits waitForTimeout()
page.route() stubs Live prod API in CI
storageState auth UI login every test
Trace on retry No CI artifacts
Isolated contexts Shared browser state
test.describe grouping 1000-line spec files

Testing Pyramid with Playwright

Many fast API tests (request fixture), moderate component tests, fewer E2E journeys. Playwright supports all three — don't run everything as E2E.

Layer Tool Speed
API request fixture Fastest
Component @playwright/experimental-ct-* Fast
E2E page fixture Slower, highest confidence

PR Review Checklist for Playwright Tests

Reviewers should verify: locators are role/label based, no hard waits, network stubbed where appropriate, test name describes user outcome, and no test.only left in code.

Common Mistakes

  • 100% E2E coverage — slow suite, team stops running it.
  • Live production API dependencies in CI tests.
  • Copy-pasting selectors instead of shared page objects or fixtures.
  • Disabling retries and traces to "speed up CI" — hides flakes.

Key Takeaways

  • Prioritize role/label locators, expect() assertions, and page.route() stubs.
  • Reuse auth with storageState; isolate tests with default contexts.
  • Enable traces on retry; tag smoke tests for fast PR feedback.
  • Follow the testing pyramid — not everything belongs in E2E.

Pro Tip

Add a ESLint rule or PR bot check that fails on waitForTimeout in spec files.