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.
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 3just uses three cloud sessions. This is the natural fit for CI sharding. - Local (emulator pool): each shard machine needs its own emulator or
device.poolwith 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:
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:
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).