Your users do not all use the same browser. Playwright makes it straightforward to test on Chromium, Firefox, and WebKit from a single test suite. Combining this with CI automation ensures every pull request is tested before it merges.
Configuring Browser Projects
Playwright uses the concept of "projects" to run the same tests across different browsers. Each project is a named configuration:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
retries: 2,
workers: 4,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
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: 'mobile-safari',
use: { ...devices['iPhone 13'] },
},
],
});The devices object includes viewport sizes, user agent strings, and device-specific settings. This means your mobile tests will run at the correct resolution with touch event simulation.
Run a specific project:
npx playwright test --project=firefoxOr run all projects:
npx playwright testParallelism
Playwright runs tests in parallel by default. The workers setting controls how many test files execute simultaneously:
export default defineConfig({
workers: process.env.CI ? 2 : 4,
});On your local machine, use more workers for faster feedback. In CI, limit workers based on available CPU and memory. Each worker launches its own browser instance, so resource usage scales linearly.
You can also shard tests across multiple CI machines:
# Machine 1
npx playwright test --shard=1/3
# Machine 2
npx playwright test --shard=2/3
# Machine 3
npx playwright test --shard=3/3Sharding splits your test suite evenly, so three machines finish roughly three times faster than one.
GitHub Actions Workflow
Here is a complete workflow that runs Playwright tests on every pull request:
# .github/workflows/playwright.yml
name: Playwright Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Build application
run: npm run build
- name: Run Playwright tests
run: npx playwright test
- name: Upload test report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 14The if: always() condition on the upload step ensures the HTML report is uploaded even when tests fail. This lets you download and inspect the report directly from the GitHub Actions run.
Reporting
Playwright supports multiple reporters. Configure them in playwright.config.ts:
export default defineConfig({
reporter: [
['html', { open: 'never' }],
['junit', { outputFile: 'results.xml' }],
['list'],
],
});- html: Interactive report you can open in a browser.
- junit: XML format that CI tools like GitHub Actions can parse and display.
- list: Simple console output showing each test result.
Open the HTML report locally after a test run:
npx playwright show-reportHandling Flaky Tests
Flaky tests pass sometimes and fail other times. Playwright helps manage them:
export default defineConfig({
retries: process.env.CI ? 2 : 0,
});Setting retries in CI means a test gets up to two more attempts before being marked as failed. Playwright marks retried tests as "flaky" in the report, making them easy to identify and fix.
Key Takeaways
- Use
projectsto test across Chromium, Firefox, WebKit, and mobile devices. - Control parallelism with
workersand distribute across machines with--shard. - Always upload test reports as artifacts in CI for easy debugging.
- Set
retriesin CI to handle occasional flakiness without blocking merges. - Use
npx playwright install --with-depsin CI to install browsers with system dependencies.