Skip to contentPlayForge

How do I run Playwright tests in GitHub Actions?

Written by Jatin Thacker, Automation Architect · Updated

Add a workflow file under .github/workflows/ that checks out the code, sets up Node, runs npm ci, npx playwright install --with-deps and npx playwright test, then uploads the playwright-report folder as an artifact. GitHub runs it on every push and pull request you list under on:.

This answer is one piece of Chapter 27: CI/CD.

  • CI/CD with GitHub Actions
  • CI with Jenkins
  • CI with Azure DevOps
  • CI with GitLab CI
  • Practice and interview questions: Debugging, Tracing & CI/CD

A pipeline runs the same command you run locally, on a clean machine, every time someone pushes. The workflow below is the one in the Playwright CI guide.

Two steps are easy to get wrong. npx playwright install --with-deps downloads the browsers and the Linux libraries they need; without it the runner has no browser. The upload step has if: ${{ !cancelled() }}, so the report is uploaded even when tests fail, which is exactly when you need it. Without it, the step gets GitHub's default success() check and is skipped after a failing test step.

The config usually changes behaviour on CI through process.env.CI, which GitHub sets. The example config forbids test.only, allows two retries, runs one worker and writes the HTML report without trying to open it. trace: 'on-first-retry' records a trace for any test that needed a retry.

To read a failure, open the run's Artifacts section, download playwright-report, unzip it and run npx playwright show-report on the folder (see qa-083).

The workflow was not pushed for this page. The output is a local run of the same npx playwright test command with CI=true set.

playwright.yml(https://practice.learnplayforge.com)
# .github/workflows/playwright.yml name: Playwright Tests on: push: branches: [ main, master ] pull_request: branches: [ main, master ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: lts/* - name: Install dependencies run: npm ci - name: Install Playwright Browsers run: npx playwright install --with-deps - name: Run Playwright tests run: npx playwright test - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} with: name: playwright-report path: playwright-report/ retention-days: 30 // playwright.config.js import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: '.', forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { baseURL: 'https://practice.learnplayforge.com', trace: 'on-first-retry', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], });
Output
$ CI=true npx playwright test

Running 2 tests using 1 worker

  ok 1 [chromium] › cart.spec.js:3:1 › the cart starts empty (315ms)
  ok 2 [chromium] › cart.spec.js:8:1 › adding the grinder updates the total (1.2s)

  2 passed (2.6s)
Test yourself
You remove if: ${{ !cancelled() }} from the upload step, and a test fails on CI. What happens to the report?

Practised in the full course: the drill Conditional artifact upload.

See the chapter

AI can write the test now. The job is knowing whether it checks anything. That's what the course teaches, one chapter at a time.

163 lessons · 226 drills · start free

← All questions

Training a team? Talk to us.