Skip to main content

Configuration and Running

playwright.config.ts is where you decide which browsers run, how many tests run at once, what happens on failure and what gets reported. This page walks through the sample project's config line by line, then covers the commands you run every day. It is the load model and execute pages of the JMeter track, for a runner that cares about correctness rather than load.

The Config, Line by Line​

playwright/sample/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: process.env.CI ? 'blob' : 'html',
use: {
baseURL: 'https://www.saucedemo.com',
testIdAttribute: 'data-test',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
storageState: 'playwright/.auth/user.json',
},
dependencies: ['setup'],
},
],
});
OptionWhat it doesMy setting and why
testDirWhere spec files live./tests
fullyParallelRun tests inside one file in parallel too, not just across filestrue. Requires isolated tests, which you want anyway
forbidOnlyFail the run if a test.only was left inOn in CI only. Locally test.only is a useful focus tool
retriesRe-run a failed test this many times before calling it failed2 in CI, 0 locally. A test that passes on retry is reported as flaky, not passed
workersNumber of parallel worker processes1 in CI (predictable on small runners), default locally (half your CPU cores)
reporterHow results are reportedhtml locally, blob in CI so shards can be merged (Section 10)
use.baseURLPrefix for page.goto('/')The environment under test. Override per environment with an env var
use.testIdAttributeAttribute getByTestId readsdata-test because saucedemo uses that. Default is data-testid
use.traceWhen to record a traceon-first-retry (Section 7)
use.screenshotWhen to take a screenshotonly-on-failure
projectsNamed browser and settings combinationsA setup project that logs in, and chromium that depends on it (Section 9)

Timeouts​

Defaults are sensible. Know them before changing them:

TimeoutDefaultSet with
Test timeout (whole test)30 stimeout: 60_000 at the top level
Assertion timeout (expect)5 sexpect: { timeout: 10_000 }
Action timeout (click, fill)none, bounded by the test timeoutuse: { actionTimeout: 10_000 }
Navigation timeoutnoneuse: { navigationTimeout: 30_000 }

Raising the test timeout to hide a slow app is the UI equivalent of raising the JMeter response-time SLA. Fix the wait instead.

Environments​

Do not hardcode staging in the config. Read it from the environment with a default:

use: {
baseURL: process.env.BASE_URL ?? 'https://www.saucedemo.com',
},
BASE_URL=https://staging.example.com npx playwright test

On Windows PowerShell: $env:BASE_URL="https://staging.example.com"; npx playwright test.


Projects: Browsers and Devices​

The generated config has commented-out projects for Firefox, WebKit, mobile and branded browsers. Uncomment what you need:

projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
{ name: 'Google Chrome', use: { ...devices['Desktop Chrome'], channel: 'chrome' } },
],
  • chromium, firefox, webkit are the bundled engines. Install them with npx playwright install.
  • channel: 'chrome' or 'msedge' uses the installed branded browser instead of the bundled one.
  • Since 1.57 the default chromium project runs headed tests in Chrome for Testing and headless tests in a slimmer chrome-headless-shell. Both are downloaded by npx playwright install chromium.

Run one project with --project:

npx playwright test --project chromium

Tip: Start with Chromium only. Add Firefox and WebKit once the suite is stable. Every extra browser multiplies run time and the number of ways a test can be flaky.


Running Tests​

CommandWhat it does
npx playwright testEverything, headless, all projects
npx playwright test tests/login.spec.tsOne file
npx playwright test -g "cart"Tests whose full name matches
npx playwright test --project chromiumOne project
npx playwright test --headedWatch the browser
npx playwright test --uiUI mode (Section 7)
npx playwright test --debugInspector, step by step
npx playwright test --workers 4Fixed worker count
npx playwright test --retries 2Override retries
npx playwright test --last-failedOnly the failures from the previous run
npx playwright test --only-changedOnly spec files changed since the last commit
npx playwright test --listPrint the tests without running them
npx playwright show-reportOpen the last HTML report

The sample package.json wraps the common ones as scripts (npm test, npm run test:ui, npm run report) so nobody has to remember the flags.

Tags​

Tag tests to run subsets:

test('valid user lands on the products page', { tag: '@smoke' }, async ({ page }) => {
// ...
});
npx playwright test --grep @smoke
npx playwright test --grep-invert @slow

Parallelism​

Playwright runs worker processes, each with its own browser. Tests in different files always run in parallel across workers. fullyParallel: true also spreads tests from the same file across workers.

This only works if tests are isolated: own data, own login state, no shared mutable records. If two tests must run in order, opt out for that file:

test.describe.configure({ mode: 'serial' });

Treat serial as a smell to fix later, not a design.


Reports​

HTML Report​

reporter: 'html' writes playwright-report/index.html after every run. Open it with npx playwright show-report. It lists every test, its duration, retries, the error, screenshots, and a link to the trace when one was recorded. Since 1.57 it also has a Speedboard tab with the slowest tests.

Other Reporters​

ReporterUse
listOne line per test in the terminal. Good default for local runs
lineCompact, one updating line
dotOne character per test
junitXML for CI systems that read JUnit
jsonMachine-readable results
blobRaw results for merging sharded runs (Section 10)

Combine them: reporter: [['list'], ['html']]. Add one for a single run without editing the config: npx playwright test --add-reporter junit.


Tips​

  • Retries hide problems. Use them in CI to survive network blips, but read the flaky count in the report. A rising flaky count is a bug list.

  • One config, many environments. Env vars for base URL and credentials. Never a config file per environment.

  • Keep workers: 1 in CI until the suite is proven isolated, then raise it. Going parallel first and debugging isolation later is painful.

  • Commit playwright.config.ts, ignore playwright-report/ and test-results/. The init command already writes the right .gitignore.