Skip to content

Playwright Test Runner

Playwright ships with @playwright/test, a full test runner — not just a browser library. This lesson explains how it discovers specs, runs workers in parallel, and reports results.

What the Test Runner Provides

@playwright/test bundles test definition (test, test.describe), assertions (expect), fixtures (page, context, browser), configuration (playwright.config.ts), and reporters (HTML, JSON, JUnit).

By default, tests in different files run in parallel across worker processes. Each worker gets isolated browser contexts, so tests do not share cookies or storage unless you explicitly configure otherwise.

npx playwright test                    # all specs, all projects
npx playwright test --grep @smoke        # filter by title/tag
npx playwright test --project=firefox  # single browser project
npx playwright test --workers=4        # limit parallelism

The CLI is the same entry point locally and in CI.

Core Runner APIs

import { test, expect } from '@playwright/test';

test('example', async ({ page }) => { /* ... */ });
test.skip('not ready', async ({ page }) => { });
test.only('debug one', async ({ page }) => { }); // local only
test.fixme('known bug', async ({ page }) => { });
  • test() registers a test function invoked by the runner.
  • test.describe() groups tests and hooks (beforeEach, afterEach).
  • test.skip / test.fixme mark tests intentionally not run.
  • Fixtures are declared in the test function signature and injected by the runner.

Test Runner CLI Cheat Sheet

Common flags for day-to-day and CI usage.

Flag Purpose
--grep <pattern> Run tests whose title matches regex
--grep-invert Exclude tests matching pattern
--project=<name> Run one browser/device project
--workers=N Control parallel worker count
--retries=N Override config retry count
--reporter=html Generate HTML report
--shard=1/3 Run a fraction of the suite (CI splitting)
--last-failed Re-run only failures from last run

Projects vs Workers

Projects in config define browser/device combinations. Each test runs once per matching project unless you filter with --project. Workers control how many tests run simultaneously — higher workers mean faster suites but more CPU/RAM.

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

Reporters for Local and CI

  • list — terminal output (default).
  • html — interactive HTML report with traces.
  • junit — XML for Jenkins, Azure DevOps, etc.
  • github — annotations in GitHub Actions.

Common Mistakes

  • Importing playwright instead of @playwright/test and losing auto-waiting assertions.
  • Using test.only in committed code, silently skipping the rest of the suite.
  • Setting workers too high on resource-constrained CI agents.
  • Expecting serial execution within a file — tests in one file run parallel by default.

Key Takeaways

  • @playwright/test is an all-in-one runner, not optional.
  • Parallel workers and isolated contexts are defaults.
  • Projects map tests to browser/device configurations.
  • CLI flags filter, shard, and report the same way locally and in CI.

Pro Tip

Add test.describe.configure({ mode: 'serial' }) only when tests in a file truly share state — otherwise keep parallel for speed.