guide

Implement Playwright in GitHub Actions for CI/CD

Implementing Playwright in GitHub Actions for CI/CD: A Comprehensive Guide

This post is prepared to help you seamlessly integrate Playwright with GitHub Actions. Whether you’re a newcomer or a seasoned developer, we’ll cover everything from setup to scaling, with a dash of humor and precision!


Introduction to Playwright & GitHub Actions

When it comes to modern browser automation and end-to-end testing, Playwright and GitHub Actions make a perfect duo. Playwright is a framework that supports testing across all major browsers (Chromium, Firefox, and WebKit) using a single API. In other words, Playwright allows you to script browser interactions in a headless mode, making it ideal for robust UI tests and web scraping.

On the other hand, GitHub Actions is a CI/CD platform built into GitHub that automates your development workflows. By combining these two tools, you can automate browser tests directly in your CI/CD pipeline, ensuring your applications are continuously tested with every code change.

Why combine them?
Integrating Playwright tests into a GitHub Actions pipeline ensures you catch bugs early, automate browser checks as part of your development cycle, and effectively improve release efficiency. For example, every time you push code, GitHub Actions can spin up a headless browser via Playwright to ensure your app performs as expected.


Step-by-Step Setup: Playwright with GitHub Actions

This section will guide you through setting up Playwright in a GitHub Actions workflow from scratch. The end goal? Fully automated tests for every code change.

Step 1: Install Playwright

In your Node.js project, add Playwright:

# Install Playwright test runner and browsers
npm install --save-dev @playwright/test

# (Optional) Initialize Playwright tests structure
npx playwright init

The npx playwright init command helps beginners by setting up an example test structure and generating a sample GitHub Actions workflow file.

Here’s an example Playwright test:

// tests/example.spec.js
const { test, expect } = require('@playwright/test');

test('homepage has expected title', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveTitle(/Example Domain/);
});

The above test navigates to example.com and checks if the page title matches “Example Domain”. You can run it locally using:

npx playwright test

Step 2: Create a GitHub Actions Workflow

To automate tests in GitHub Actions:

  1. Create a workflow file .github/workflows/playwright.yml.
  2. Define on triggers (e.g., on push or pull_request events).
  3. Set up a job to run on a GitHub-hosted runner.
  4. Invoke Playwright to execute your tests.

Here’s a simple workflow file:

name: Playwright Tests

on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    
    steps:
      # Checkout code
      - name: Checkout repository
        uses: actions/checkout@v3

      # Set up Node.js
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18

      # Install dependencies and browsers
      - name: Install dependencies
        run: npm install

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      # Run tests
      - name: Run Playwright tests
        run: npx playwright test

What’s happening here:

  1. The workflow triggers on pushes or pull requests to main.
  2. The job uses a hosted Ubuntu runner to execute steps.
  3. The steps include checking out code, installing deps, setting up Playwright browsers, and running the tests.

Integrating Playwright Tests in CI

Headless Mode

By default, Playwright tests run headlessly (no visible UI), making it perfect for CI.

Environment Variables

GitHub Actions sets CI=true automatically, which you can use to adjust test behavior for CI environments. For example:

retries: process.env.CI ? 2 : 0

Test Reports

To debug failed tests, Playwright can generate an HTML report. Add it as an artifact in your workflow:

      - name: Save Playwright test report
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/

This stores the report so you can view it after the workflow finishes.


Handling Common Challenges in CI

Flaky Tests and Timing Issues

In CI environments, flaky tests (those that sometimes fail) are a common challenge due to timing issues or shared runner resources.

How to fix flaky tests:

  1. Retries: Configure retries in your Playwright configuration for CI:

    retries: process.env.CI ? 2 : 0,
    
  2. Increase Timeouts: Adjust timeouts for slower environments, e.g.,:

    testTimeout: 60 * 1000, // 60 seconds
    
  3. Proper Waiting: Use Playwright’s wait methods instead of fixed delays. For instance:

    await expect(page).toHaveText('Welcome');
    

Parallel Execution in CI

Playwright runs tests in parallel by default, maximizing performance. However, on GitHub Actions (which has 2 CPU cores), you should limit the number of workers:

workers: process.env.CI ? 2 : undefined,

To further speed up tests, you can shard them across jobs:

strategy:
  matrix:
    shard: [1, 2]
steps:
  - name: Run tests (Shard ${{ matrix.shard }})
    run: npx playwright test --shard=${{ matrix.shard }}/2

Scaling with Hosted Environments (Using BrowserCat)

For scalable CI pipelines, consider offloading heavy browser tasks to a cloud service like BrowserCat. BrowserCat provides cloud-hosted browsers, allowing you to significantly amplify your test setup without overloading GitHub’s runners.

Key Benefits of BrowserCat:

  • Unlimited parallel browser sessions.
  • More reliable and consistent test runs (no resource constraints).
  • Easy integration – set BrowserCat’s WebSocket endpoint in your Playwright setup.

For example:

const { chromium } = require('@playwright/test');

const browser = await chromium.connect({
  wsEndpoint: 'wss://cloud.browsercat.com',
});

This approach reduces CI times while increasing test stability and scalability.


Real-World Benefits of Automating with Playwright

Use Cases

  1. Regression Testing: Automatically catch bugs on every code push.
  2. Cross-Browser Testing: Verify compatibility across Chrome, Firefox, and Safari.
  3. API & Front-End Validation: Run end-to-end flows to ensure back-end and front-end integrations remain functional.
  4. Deployment Monitoring: Schedule nightly test runs to ensure production remains bug-free.

Conclusion

Combining Playwright and GitHub Actions allows developers to create robust, scalable, and automated CI/CD pipelines. With clear benefits like catching bugs early, faster feedback loops, and reliable builds, it’s no wonder many teams adopt this setup. And if you’re scaling aggressively, platforms like BrowserCat can make your test pipelines even faster and more efficient.

Automate confidently and keep your pipelines green! 🟢 Happy testing!

Automate Everything.

Tired of managing a fleet of fickle browsers? Sick of skipping e2e tests and paying the piper later?

Sign up now for free access to our headless browser fleet…

Get started today!