Testing

Playwright

A framework for end-to-end tests and browser automation: Chromium, Firefox and WebKit from one API.

What it is

Microsoft created Playwright in 2020 with a team that earlier built Puppeteer at Google. It drives real browsers (Chromium, Firefox, WebKit) and supports JavaScript / TypeScript, Python, Java and .NET.

Key features: auto-waiting (elements are awaited automatically), isolated browser contexts per test, parallel runs, mobile device and network emulation. The trace viewer records steps, snapshots and network for analyzing failures.

It has test generation from recorded actions (codegen), a built-in test runner and an HTML report. Playwright is also used for scraping and automation, not only tests.

Use it when

  • End-to-end tests of critical flows: login, payment, forms.
  • You need cross-browser checks, including Safari (WebKit).
  • You want stable tests with auto-waiting and traces for CI.

Avoid it when

  • Unit tests of individual functions: Vitest or Jest are faster.
  • Component tests where jsdom is enough.
  • Do not use E2E as the only layer: it is slower and more brittle than unit tests.

Key concepts

Auto-waiting
Before an action Playwright waits until the element is visible and actionable.
Locators
Resilient selectors by role, text or test id: getByRole, getByText.
Browser context
An isolated browser profile per test: separate cookies and storage.
Trace viewer
A recording of steps with DOM snapshots, network and console for failure analysis.
Fixtures
Preparing state and dependencies for tests through test.extend.

Example

An E2E login test using role locators.

Cheat sheet

Playwright cheat sheet
Command or codeWhat it does
npx playwright testRun all tests
npx playwright test --uiRun in UI mode with debugging
npx playwright codegen https://example.comRecord steps into a test
npx playwright show-reportOpen the HTML report
await page.goto("/login")Open a page
await page.getByRole("button", { name: "Save" }).click()Click by role and name
await page.getByLabel("Email").fill("[email protected]")Fill a field by its label
await expect(page.getByText("Saved")).toBeVisible()Assertion with auto waiting
await page.route("**/api/user", r => r.fulfill({ json: {} }))Mock a network response
test.use({ storageState: "auth.json" })Reuse a saved login

How to learn it

  1. Install Playwright with npm init playwright@latest and run the example that comes with the project.
  2. Take the Testing basics course on ShortLesson to see where e2e tests fit among other kinds.
  3. Write a first test: open a page, find an element by role or text, check the result with expect.
  4. Learn locators (getByRole, getByLabel, getByTestId) and auto waiting instead of sleep.
  5. Use the tools: UI mode, trace viewer, codegen to record steps, debugging with --debug.
  6. Log in once through storageState instead of in every test, and structure code with Page Objects.
  7. Mock the network with page.route, test APIs with request and run on several browsers and mobile viewports.
  8. Run tests in CI (GitHub Actions) with parallelism, retries and saved report and trace.

Interview questions

  1. 1. What is auto-waiting?

    Before each action (click, input) Playwright checks the element exists, is visible, stable and not covered. So you do not need manual sleep, which makes tests flaky.

  2. 2. Why is getByRole better than CSS selectors?

    Role and text locators match what the user sees and break less when markup changes. They also check accessibility.

  3. 3. How do you isolate tests?

    Each test gets a new browser context with clean cookies and storage. For login you can save the storage state and reuse it.

  4. 4. How do you analyze a failure in CI?

    Enable trace (trace: 'on-first-retry') and open it in the trace viewer: you see steps, page snapshots, network and errors.

Interview questions from the bank

Comparisons with this technology

Logos belong to their owners and are used for identification only. Icons: Simple Icons (CC0), Devicon (MIT).