For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /guide/advanced/ci.md.
close
  • English
  • CI

    Rstest uses the same CLI in CI as it does locally. The main difference is that CI should run tests in run mode with rstest, then upload any reports that other tools need to read.

    Basic workflow

    Use rstest in CI so the process exits after one test pass. If your project already has a test script, keep CI calling that script and make the script run rstest.

    package.json
    {
      "scripts": {
        "test": "rstest"
      }
    }

    A minimal GitHub Actions workflow installs dependencies, restores the package-manager cache, and runs the test script:

    .github/workflows/test.yml
    name: Test
    
    on:
      push:
      pull_request:
    
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
    
          - uses: pnpm/action-setup@v4
            with:
              version: 11
    
          - uses: actions/setup-node@v4
            with:
              node-version: 22.12.0
              cache: pnpm
    
          - run: pnpm install --frozen-lockfile
          - run: pnpm test

    When Rstest detects GitHub Actions and no reporter is manually configured, it automatically enables the github-actions reporter. Failed assertions are turned into GitHub annotations, and a Markdown summary is appended to the workflow summary. See reporters for reporter details.

    Other CI systems can use the same commands. The important part is to run pnpm install --frozen-lockfile before pnpm rstest or your package script.

    Add coverage

    Coverage collection is opt-in. Install the provider you want to use before enabling --coverage:

    pnpm add @rstest/coverage-istanbul -D
    pnpm rstest --coverage

    Upload the generated coverage/ directory if your CI needs to keep the HTML report or pass coverage data to another service:

    - run: pnpm rstest --coverage --coverage.reportOnFailure
    
    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: coverage
        path: coverage

    Use if: always() when the report is useful for failed runs too. For available providers, reporters, thresholds, and output paths, see coverage.

    Run browser tests in CI

    Rstest Browser Mode and @rstest/playwright both use Playwright to launch browsers. Installing the playwright npm package provides the automation API, but the browser executable must be provided separately.

    Choose how to provide the browser

    The portable default is to install the Playwright browser that matches the package version:

    pnpm exec playwright install --with-deps chromium

    Choose the setup that matches the coverage and reproducibility your workflow needs:

    RequirementBrowser setup
    Fast Chrome runs on a standard GitHub-hosted runnerSkip playwright install and launch the preinstalled Chrome with channel: 'chrome'.
    A Chromium version pinned to the Playwright packageRun playwright install --with-deps chromium. For headless-only runs without a channel, add --only-shell to skip the full headed Chromium download.
    Firefox or WebKit coverageInstall the matching Playwright browser with playwright install --with-deps firefox or playwright install --with-deps webkit.
    A self-hosted runner, container job, or custom imageInstall the Playwright browser, or provision Chrome in the image before selecting channel: 'chrome'.

    The standard GitHub-hosted runner images, including ubuntu-latest, provide Google Chrome. Selecting its chrome channel lets both Rstest integrations use that executable without downloading Playwright Chromium. GitHub updates runner software regularly, so this trades a pinned browser revision for faster setup. The workflow's Set up job → Runner Image → Included Software link shows the exact software for a run.

    Firefox and WebKit still require Playwright's browser downloads. Playwright relies on patched builds for those engines and cannot substitute the Firefox or Safari applications installed on the runner.

    Browser mode

    Install @rstest/browser and the Playwright API:

    pnpm add @rstest/browser playwright -D

    On a standard GitHub-hosted runner, pass the Chrome channel through the Browser Mode CLI and omit the browser installation step:

    - run: pnpm install --frozen-lockfile
    - run: pnpm rstest --browser --browser.providerOptions.launch.channel=chrome

    To keep the same optimization behind an environment check in rstest.config.ts, configure the provider instead:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        providerOptions:
          process.env.GITHUB_ACTIONS === 'true'
            ? {
                launch: {
                  channel: 'chrome',
                },
              }
            : undefined,
      },
    });

    In CI, browser.headless defaults to true, so no additional headless configuration is needed. See Browser Mode getting started and browser configuration for other browser and provider options.

    @rstest/playwright

    Install the Rstest fixtures and the Playwright API:

    pnpm add @rstest/playwright playwright -D

    @rstest/playwright configures launch options through its playwright fixture. Define a shared extended test, then import it from browser test files:

    tests/fixtures.ts
    import { expect, test as base } from '@rstest/playwright';
    import type { PlaywrightOptions } from '@rstest/playwright';
    
    export { expect };
    
    export const test = base.extend({
      playwright: {
        browserName: 'chromium',
        launchOptions:
          process.env.GITHUB_ACTIONS === 'true' ? { channel: 'chrome' } : undefined,
      } satisfies PlaywrightOptions,
    });

    With this fixture, a standard GitHub-hosted workflow only needs to install npm dependencies and run Rstest; do not add a playwright install step. See the @rstest/playwright guide for fixture usage and trace artifacts.

    Split tests with shards

    Use --shard <index>/<count> when the full suite is stable but too slow for one CI machine. Each shard runs a different subset of test files. To combine results and coverage afterward, run every shard with the blob reporter, upload the blob files, then merge them in a follow-up job.

    jobs:
      test:
        runs-on: ubuntu-latest
        strategy:
          fail-fast: false
          matrix:
            shard: [1, 2, 3]
        steps:
          - uses: actions/checkout@v4
          - uses: pnpm/action-setup@v4
            with:
              version: 11
          - uses: actions/setup-node@v4
            with:
              node-version: 22.12.0
              cache: pnpm
          - run: pnpm install --frozen-lockfile
          - run: pnpm rstest --shard ${{ matrix.shard }}/3 --reporters=blob --coverage
          - uses: actions/upload-artifact@v4
            if: always()
            with:
              name: rstest-blob-${{ matrix.shard }}
              path: .rstest-reports
              include-hidden-files: true
    
      merge-reports:
        runs-on: ubuntu-latest
        needs: test
        if: always()
        steps:
          - uses: actions/checkout@v4
          - uses: pnpm/action-setup@v4
            with:
              version: 11
          - uses: actions/setup-node@v4
            with:
              node-version: 22.12.0
              cache: pnpm
          - run: pnpm install --frozen-lockfile
          - uses: actions/download-artifact@v4
            with:
              pattern: rstest-blob-*
              path: .rstest-reports
              merge-multiple: true
          - run: pnpm rstest merge-reports --coverage --cleanup

    Each shard writes .rstest-reports/blob-{index}-{count}.json. The merge job collects those files into one .rstest-reports/ directory, then rstest merge-reports runs the configured reporters on the unified result and merges coverage data. See sharding and rstest merge-reports for details.

    Publish machine-readable reports

    CI tools often need structured report files in addition to terminal output. Add reporters when you need XML, JSON, Markdown, or blob output:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      reporters: [
        'default',
        ['junit', { outputPath: './reports/junit.xml' }],
        ['json', { outputPath: './reports/rstest.json' }],
      ],
    });

    Then upload the report directory:

    - run: pnpm rstest
    
    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: rstest-reports
        path: reports

    Use junit for CI test-result integrations, json for custom tooling, md for Markdown summaries, github-actions for GitHub annotations, and blob for sharded report merging. See reporters for the complete list and options.

    Cache dependencies

    Start with the package-manager cache because it is safe and usually gives the biggest CI improvement. In GitHub Actions, actions/setup-node with cache: pnpm restores the pnpm store based on the lockfile.

    Do not cache Playwright browser binaries by default. Restoring the cache can take about as long as downloading the browser, and Linux system dependencies are not included in that cache. Prefer the preinstalled GitHub Chrome when its version policy fits your workflow; otherwise install only the required browser and use --only-shell for headless-only Chromium runs.

    • Use Node.js ^20.19.0 or >=22.12.0 to match Rstest's supported runtime range.
    • Run rstest in CI, either directly or through a package script.
    • Install coverage and browser packages only when the workflow needs those features.
    • Upload coverage, JUnit, JSON, or blob artifacts with if: always() if they help debug failures.
    • Add sharding only after the single-machine workflow is stable.
    • Choose explicitly between a version-matched Playwright browser and a preinstalled system Chrome, and keep the selected browser, channel, and installation step aligned.