Skip to main content

Sharding

Sharding splits your test suite into smaller parts, called shards, that run as independent processes, typically one per CI machine. A four-way split runs roughly a quarter of the tests on each of four jobs, cutting wall-clock time. Taqwright uses the Playwright runner's sharding, with one mobile-specific rule: each shard still needs its own device capacity.

Split a run with --shard

Pass --shard x/n to run shard x of n. Launch the shards as separate processes (usually separate CI jobs):

npx taqwright test --shard 1/4
npx taqwright test --shard 2/4
npx taqwright test --shard 3/4
npx taqwright test --shard 4/4

Tests are divided at the file level by default. Set fullyParallel: true in your config to split at the individual-test level for a more even spread (see Balancing shards).

Shard across machines

Each --shard invocation is a completely independent process. Taqwright splits the test list; it does not allocate devices. Every shard needs enough device capacity for the workers it runs.

Each shard needs its own devices

A shard does not bring a device with it. Size each shard's device capacity to its --workers:

  • Cloud (BrowserStack / LambdaTest): each worker opens its own independent session, so a shard with --workers 3 just uses three cloud sessions. This is the natural fit for CI sharding.
  • Local (emulator pool): each shard machine needs its own emulator or device.pool with an entry per worker. There is no coordination of devices across shards.

See Parallelism for device pools, workers, and cloud sessions.

Because cloud workers are independent sessions, a cloud project shards cleanly across CI jobs: give each job credentials and a shard index, and let the provider queue the device contention.

Balancing shards

With fullyParallel: true, tests are distributed across shards at the test level, which keeps the shards evenly loaded:

taqwright.config.ts
import { defineConfig, Platform } from '@taqwright/taqwright';

export default defineConfig({
fullyParallel: true, // taqwright defaults to false (file-level)
projects: [/* ... */],
});

Without it, tests split at the file level, so a few large files can leave some shards heavier than others. Keeping test files similarly sized helps.

Merge reports from shards

Each shard produces its own results, so have every shard write the blob reporter, collect the blobs into one directory, then merge them into a single report:

# On each shard
npx taqwright test --shard 1/4 --reporter blob

# After all shards finish, with every blob gathered into ./all-blobs
npx taqwright merge-reports ./all-blobs --reporter html

See Reporters for the blob reporter and Command line for merge-reports and show-report.

GitHub Actions example

Run the shards as a matrix against a cloud project, upload each shard's blob as an artifact, then merge them in a dependent job:

.github/workflows/tests.yml
name: tests
on: push

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm ci
- name: Run shard
run: >
npx taqwright test
--project browserstack-android
--shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
--reporter blob
- uses: actions/upload-artifact@v4
with:
name: blob-${{ matrix.shardIndex }}
path: blob-report
retention-days: 1

merge:
if: always()
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm ci
- name: Download blobs
uses: actions/download-artifact@v4
with:
path: all-blobs
pattern: blob-*
merge-multiple: true
- name: Merge into one HTML report
run: npx taqwright merge-reports all-blobs --reporter html
- uses: actions/upload-artifact@v4
with:
name: html-report
path: playwright-report

The test job fans out into four parallel shards, each opening its own BrowserStack sessions; the merge job runs once they all finish and produces a single HTML report. To shard on local emulators instead, give each runner its own device or device.pool and point --project at an emulator project (see Projects).