skip to content

What does Playwright's --shard=1/4 flag do to the set of tests a run executes?

level: juniorimportance: must knowfreq 68%

answer

  1. One machine runs one slice
  2. Index is one-based, not zero
  3. Shards never talk to each other
  4. Config option mirrors the flag
  5. Green shard is not green suite

basics

~20 s

Playwright splits the selected tests into four disjoint groups and runs only the first. Each shard is an independent run on its own machine, so all four have to be executed before the suite is covered.

solid answer

~40 s

`--shard=1/4` tells this Playwright run that it is slice one of four. The runner builds the list of tests the run selected, divides that list deterministically into four disjoint groups, keeps group one and skips the rest. The index is one-based, so a four-way split is `1/4` through `4/4`, and the same thing can be declared in the config as `shard: { current: 1, total: 4 }`. Shards are independent processes with no coordination: no shared browser, no shared state, no rebalancing at runtime. A shard exiting zero therefore means only that its own quarter passed. CI has to launch all four jobs with the same total and combine their outcomes before calling the suite green.

code

bash · 4 lines
bash
npx playwright test --shard=1/4 --reporter=blob
npx playwright test --shard=2/4 --reporter=blob
npx playwright test --shard=3/4 --reporter=blob
npx playwright test --shard=4/4 --reporter=blob

go deeper

for a junior

Remember the shape of the flag: --shard=<index>/<total>, one-based, and every index from 1 to the total has to be run somewhere. Running a single shard covers only that fraction of the suite.

for a middle

Be able to explain that the split is computed before execution from the selected test list, that it is identical in every job, and that a shard is a subset of tests while a worker is a process inside one run.

for a senior

Show that you gate the pipeline on all shard outcomes, keep the total identical across jobs, and treat per-shard reports as partial evidence that still has to be merged before anyone reads it.

for a principal

Own the invariant that the split is a pipeline-level contract: one place defines the total, jobs cannot drift from it, and the suite's verdict is defined as the combination of shard results rather than any single job.

## What `--shard` divides Playwright Test first builds the list of tests a run will execute, after project selection and any path or `--grep` filters have been applied. `--shard` slices that list. `--shard=1/4` says *this process is slice one of four*. The slices are disjoint and their union is the whole selected list, so no test is dropped and no test runs twice. The division is **static and computed before anything executes**. Every shard walks the same repository, produces the same ordered list of units, applies the same arithmetic, keeps its own slice and discards the rest. That is what makes the scheme safe across machines that never talk to each other: it needs no coordinator, no queue and no lock, only the same code and the same total. ## The index is one-based A four-way split is `--shard=1/4`, `--shard=2/4`, `--shard=3/4` and `--shard=4/4`. There is no shard zero. The second number is the **total**, and it is the part a pipeline most often gets wrong: if one job passes `1/4` while another passes `2/5`, the slices stop being a partition of the suite, and the run quietly executes some tests twice and never executes others. ## Declaring it in the config instead The same split exists as a config option, which is useful when a wrapper script rather than a raw CLI call starts the run: ```ts import { defineConfig } from '@playwright/test'; export default defineConfig({ fullyParallel: true, shard: { current: Number(process.env.SHARD_INDEX), total: 4 }, }); ``` The option takes an object with `current` and `total`, not the `1/4` string the flag uses. Command-line options override the config, so a `--shard` argument wins over a `shard` block if both are present. ## What a shard is not - It is **not** a worker. Workers are the parallel processes inside one machine's run; a shard is the subset of tests one machine was handed. A single shard still starts several workers of its own. - It is **not** a retry pool. A test that fails in shard 2 is never attempted by shard 3, because shards do not see each other's results. - It is **not** shared state. Each shard is a fresh process on its own machine, with its own browsers, its own storage state and its own setup work. - It is **not** self-balancing. Nothing is moved at run time, so a shard that finishes early simply exits and its machine goes idle. - It is **not** a verdict for the suite. Exit code zero from `--shard=1/4` means one quarter passed. ## What one shard reports A shard's console output counts only the tests it was given, and an HTML report written by a single shard contains only that shard's tests, with that shard's totals. Four shards therefore produce four partial reports and four exit codes. That is exactly why the `blob` reporter and `npx playwright merge-reports` exist: they let the four runs be stitched into one report for the whole suite. ## Turning four jobs back into one answer For a large payroll regression suite in CI the run reads: 1. Launch four jobs, each with the same `total` and a distinct `current`. 2. Give every job the `blob` reporter, so each emits a mergeable archive instead of a finished report. 3. Collect the four archives into one directory once all jobs have ended. 4. Run `npx playwright merge-reports --reporter=html ./all-blob-reports` once to get a single report with the suite's real totals. 5. Gate the pipeline on the combination of the four exit codes, never on one of them. Step 5 is not automatic. Playwright reports per shard; the pipeline is what decides that *the suite passed* means *all four shard jobs passed*. ## Why the model is shaped this way Sharding trades coordination for simplicity. Because the division is a pure function of the test list and the two numbers, a shard needs nothing from its peers and can start the moment a machine is free. The price is that the split is only as even as the units being split, and that stitching results back together is a separate step you have to run yourself.

  • One job in a four-way split was given --shard=2/5 by mistake. What happens to the run?
    Nothing fails loudly. Each shard computes its slice from its own numbers, so the five-way job takes a slice sized for a different split. Some tests then run in two jobs and others run in none, while every job can still exit zero. The total has to be identical in every job for the slices to partition the suite.
  • Does sharding change how many browsers or workers a single machine runs?
    No. The shard decides only which tests that machine was given; the `workers` setting still decides how many parallel processes it uses to run them. A machine running a quarter of the suite starts the same number of workers it would have started for the whole suite.

Sharding is like dealing one deck into four hands before play starts: every card goes somewhere, each player sees only their own hand, and nobody passes cards across the table once play begins.

saying these in an interview costs you the question

  • Thinks the first shard is --shard=0/4
  • Believes a green shard means the whole suite passed
  • Expects shards to share browsers or storage state
  • Thinks a failed test moves to another shard for a retry
  • Assumes shards rebalance work between machines at run time
  • Confuses the shard count with the worker count