automationplaywrightlearning

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

  1. Install Playwright in a new project: npm init playwright@latest.
  2. Open Playwright Inspector โ€” it writes the first test for you: npx playwright codegen <url>. Not perfect code, but as a starter โ€” fine.
  3. Run tests with the --ui flag: 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.