Playwright: where to start and how to learn
Playwright became the web automation standard in 2023-2025. Compared to Selenium it gives you auto-wait, better debugging, native iframe and shadow DOM support. Compared to Cypress β multi-browser, multi-tab, no same-origin restrictions. A curated set of resources to help you switch or start fresh.
Official sources (must read)
β playwright.dev/docs/intro β official docs. Very well written, reads like a tutorial, not a reference. β playwright.dev/docs/best-practices β best practices from the Playwright team. Especially the parts about web-first assertions and locators. β playwright.dev/docs/release-notes β whatβs new in each version. Playwright moves fast, features land almost every release.
How to start practically
- Install Playwright in a new project:
npm init playwright@latest. - Open Playwright Inspector β it writes the first test for you:
npx playwright codegen <url>. Not perfect code, but as a starter β fine. - Run tests with the
--uiflag:npx playwright test --uiβ graphical trace viewer. The best automated-test debugging Iβve seen.
Topics worth understanding separately
Locators and web-first assertions
The main difference from Selenium β Locator API + expect(). Itβs not just a renamed By-selector β it auto-retries. More in my post on auto-wait.
Page Object Pattern in TypeScript
Playwright is TS-first. Page Objects come out more natural than in Selenium:
class LoginPage {
constructor(readonly page: Page) {}
async login(email: string, password: string) {
await this.page.getByLabel('Email').fill(email);
await this.page.getByLabel('Password').fill(password);
await this.page.getByRole('button', { name: 'Sign In' }).click();
}
}
API testing through Playwright
Playwright handles not just UI but API requests β request.post(...). Convenient when API tests need to live in the same framework.
Fixtures and test data
Declarative fixtures via test.extend β powerful pattern. For example, if every test needs a logged-in user β described once, used everywhere.
CI integration
Playwright understands GitHub Actions / GitLab CI natively. Parallelization, sharding, retry on flaky tests, HTML report β all built in.
Visual regression
await expect(page).toHaveScreenshot() β built-in pixel-perfect comparison. See my post on visual regression.
Beyond the docs
β Playwright YouTube (@Playwrightdev) β short 5-10 minute feature videos. Made by the Playwright team.
β Test Automation University (catalog) β free video courses including Playwright tutorials.
β Awesome Playwright (GitHub list) β curated list of resources: plugins, utilities, videos.
Beginner antipatterns
β Using page.click('css=...') β old API. Migrate to page.locator(...) or page.getByRole/getByText.
β await page.waitForTimeout(2000) β this is Thread.sleep. Breaks things in CI. Use only for debugging.
β expect(await locator.textContent()).toBe(...) β synchronous check without retry. Correct: await expect(locator).toHaveText('...').
What to do right now
β If you have Selenium and it works β donβt migrate for migrationβs sake. Add Playwright for new tests, keep the old.
β
Run npx playwright codegen on your productβs main UX flow. Youβll get a draft E2E test.
β
Enable trace: 'on-first-retry' in playwright.config.ts β gives offline debugging with a timeline of every action.
More: Playwright docs, Test Automation University, Awesome Playwright.