Skip to content
Learni
View all tutorials
Tests & Qualité

How to Get Started with Playwright in 2026

Lire en français

Introduction

Playwright is an open-source framework from Microsoft for browser automation, outperforming Selenium in speed and reliability. In 2026, it natively supports Chromium, Firefox, and WebKit with an intuitive API for robust end-to-end (E2E) tests. Why use it? It manages isolated contexts, mobile emulations, and parallel tests with minimal flakiness, cutting false positives by 80% compared to legacy tools.

This beginner tutorial takes you from the basics to actionable tests: installation, setup, page interactions, and assertions. By the end, you'll have a testable project on a simple HTML page, ready to scale. Imagine testing a login form in just 10 lines of code instead of complex setups—that's Playwright's power. (132 words)

Prerequisites

  • Node.js 20+ installed
  • Basic JavaScript/TypeScript knowledge
  • An editor like VS Code
  • Git for version control (optional)

Initialize the project and install Playwright

terminal
mkdir playwright-demo
cd playwright-demo
npm init -y
npm install -D @playwright/test
type "npx playwright install" && npx playwright install

This command creates a project folder, initializes npm, and installs Playwright as a dev dependency. npx playwright install downloads the browser binaries (Chromium by default). Don't skip this step: without it, tests fail with 'browser not found' errors.

Understanding the project structure

After installation, Playwright creates a tests/ folder with example.spec.ts. Also create tests/demo.html for our examples:

html


Demo

Playwright Demo




Result here



Serve it locally with npx serve . at http://localhost:3000.

Configure Playwright

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

This file centralizes the config: test directory, HTML reporters for visual reports, baseURL for relative URLs, and a Chromium project. trace: 'on-first-retry' captures videos/screenshots on failures. Pitfall: without baseURL, every page.goto() needs an absolute URL, bloating your code.

First test: basic navigation

tests/first.spec.ts
import { test, expect } from '@playwright/test';

test('basic navigation', async ({ page }) => {
  await page.goto('/demo.html');
  await expect(page).toHaveTitle(/Demo/);
  await expect(page.locator('h1')).toHaveText('Playwright Demo');
});

This test navigates to the page, checks the title, and the h1 with assertions. expect(page) tests the entire document; locator targets precisely. It runs standalone: copy-paste and launch. Skip page.waitForLoadState() here—expect waits implicitly.

Run your first tests

Tip: Run npx playwright test for all tests, or npx playwright test first.spec.ts for one. Open playwright-report/index.html for an interactive dashboard with videos and traces.

Interaction test: clicks and input

tests/interactions.spec.ts
import { test, expect } from '@playwright/test';

test('user interactions', async ({ page }) => {
  await page.goto('/demo.html');

  const button = page.locator('#btn');
  const input = page.locator('#input');
  const result = page.locator('#result');

  await button.click();
  await input.fill('Test Playwright');
  await input.press('Enter');

  await expect(result).toHaveText('Test Playwright clicked!');
});

Simulates a click, typing, and Enter on elements. locator('#id') is robust to DOM changes. Use await result.toContainText('...') for flexibility. Pitfall: without press('Enter'), key events don't fire, breaking JS validations.

Test with advanced assertions

tests/assertions.spec.ts
import { test, expect } from '@playwright/test';

test('advanced assertions', async ({ page }) => {
  await page.goto('/demo.html');

  await expect(page.locator('#btn')).toBeVisible();
  await expect(page.locator('#input')).toBeEnabled();

  await page.locator('#input').fill('Hello');
  await expect(page.locator('#input')).toHaveValue('Hello');

  await expect(page).toHaveScreenshot('demo-page.png');
});

Checks visibility, enabled state, and input value, plus a pixel-perfect screenshot. toHaveScreenshot captures and compares images. Update baselines with test --update-snapshots. Caution: high-DPI screens break snapshots; set viewport in config.

Multi-browser testing

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Adds Firefox and WebKit projects for cross-browser parallel tests. Run npx playwright test --project=chromium to target one. Pitfall: JS behaviors vary (e.g., Safari userAgent); try devices['iPhone 12'] for mobile.

Run tests in UI mode

terminal
npx playwright test --ui
npx playwright test --headed --slow-mo=500
npx playwright show-trace tests/interactions.spec.ts/1/trace.zip

--ui opens an interactive dashboard for debugging. --headed shows the browser, --slow-mo slows it down to watch. show-trace replays failures. Perfect for beginners: visualize step-by-step without cryptic logs.

Best practices

  • Use text locators: page.getByText('Click me') over fragile CSS.
  • Custom fixtures: Create test.extend({ user: async ({}, use) => { ... } }) for reusable setups.
  • Isolated tests: One test = one feature; use test.describe for logical suites.
  • Error handling: Add conditional test.skip(condition) and test.fail().
  • CI/CD: Integrate with GitHub Actions using playwright-github-action.

Common errors to avoid

  • Server not running: Always start npx serve before tests; otherwise, goto times out.
  • Unstable selectors: Avoid page.click('button:nth-child(2)'); prefer getByRole('button', { name: /text/ }).
  • Default timeouts: Use expect({ timeout: 10000 }) for slow pages, but investigate root causes.
  • Missing browsers: Run npx playwright install --with-deps on Linux for system libs.

Next steps

  • Official docs: playwright.dev
  • Advanced: API tests with request fixture, component testing with @playwright/experimental-ct-react.
  • Training: Check out our QA automation courses at Learni to master Playwright in production.
  • Example repo: Clone this tutorial on GitHub to experiment.