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.
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.
Continue with Playwright Do's and Don'ts to build on what you learned here.