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
Cheat sheet
| Command or code | What it does |
|---|---|
npx playwright test | Run all tests |
npx playwright test --ui | Run in UI mode with debugging |
npx playwright codegen https://example.com | Record steps into a test |
npx playwright show-report | Open 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
- Install Playwright with
npm init playwright@latestand run the example that comes with the project. - Take the Testing basics course on ShortLesson to see where e2e tests fit among other kinds.
- Write a first test: open a page, find an element by role or text, check the result with
expect. - Learn locators (
getByRole,getByLabel,getByTestId) and auto waiting instead ofsleep. - Use the tools: UI mode, trace viewer,
codegento record steps, debugging with--debug. - Log in once through
storageStateinstead of in every test, and structure code with Page Objects. - Mock the network with
page.route, test APIs withrequestand run on several browsers and mobile viewports. - Run tests in CI (GitHub Actions) with parallelism, retries and saved report and trace.
Interview questions
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. 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. 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. 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
- How do unit, integration, and e2e tests differ from each other?JuniorTesting
- How does the testing pyramid differ from the testing trophy?MiddleTesting
- How do you replace network requests in tests, and which approach is best?MiddleTesting
- What are flaky tests, why do they occur, and how do you fight them?MiddleTesting
- How does Playwright differ from Cypress, and which should you pick for a new project?MiddleTesting
- How do you write stable selectors in e2e tests?MiddleTesting
- How does BDD differ from TDD, and what is Gherkin for?MiddleTesting
- When are component tests better than e2e for the frontend?MiddleTesting
Comparisons with this technology
Related technologies
- CypressA tool for E2E and component tests that runs inside the browser with an interactive runner.
- VitestA fast Vite-based test runner with a Jest-compatible API and native TypeScript and ESM support.
- JestA testing framework for JavaScript and TypeScript: runner, assertions, mocks and coverage in one package.
- GitHub ActionsGitHub Actions is CI/CD built into GitHub: YAML workflows run on repository events such as push or pull request.
Logos belong to their owners and are used for identification only. Icons: Simple Icons (CC0), Devicon (MIT).