Four Playwright shards each produced their own HTML report - how do you get one report for the whole run?
answer
- Finished reports cannot be added up
- Emit an archive, not a report
- One zip per shard in blob-report
- merge-reports rebuilds the whole run
- Same Playwright version in every shard
basics
~20 sHave every shard run the blob reporter instead of html. Each writes one archive, CI collects them into a single directory, and npx playwright merge-reports turns that directory into one HTML report covering the whole suite.
solid answer
~40 sFinished HTML reports cannot be combined, so the shards must emit a mergeable intermediate instead. Run each shard with `--reporter=blob`; every job writes one archive into `blob-report/` whose name carries its shard number, containing that shard's results, steps, attachments and traces. CI collects the four archives into one directory, then a final job runs `npx playwright merge-reports --reporter=html ./all-blob-reports`, which rebuilds a single report with the suite's real totals. `merge-reports` can emit any reporter, so the same archives also yield `junit` or `github` output, and `--config` reuses the reporter settings already in `playwright.config.ts`. All archives must come from the same Playwright version, 1.63 here, and merging can only run after every shard has finished.
code
bash · 3 linesnpx playwright test --shard=1/4 --reporter=blob
npx playwright merge-reports --reporter=html ./all-blob-reportsgo deeper
Know that a sharded run produces one report per machine, and that Playwright ships a merge step so you do not have to read four of them. Reach for the blob reporter whenever a run is split.
Explain the two halves: the blob reporter writes a mergeable archive per shard, and merge-reports replays a directory of archives through any reporter to rebuild one report with the run's real totals.
Show the pipeline shape you would build: blob on CI only, archives collected after every shard ends including failures, one merge job, and a guard that the archive count matches the shard total.
Own the reporting contract for the org: one artefact carries the suite's verdict, versions are pinned so archives stay mergeable, and the merged report, not any single machine's output, is what humans and dashboards are pointed at.
## Why four reports cannot be added up Each shard is a complete Playwright run over a quarter of the suite, and each reporter it uses produces a finished artefact for that quarter. An HTML report is a rendered site with its own totals, its own trace links and its own index; two of them side by side are two reports, not one. The same holds for JUnit XML: concatenating the files gives a document no CI viewer treats as a single suite. Nothing downstream can reconstruct the whole run from finished outputs, so the fix is to make shards emit something *unfinished* on purpose. ## The blob reporter `blob` is that intermediate. It captures everything a run knows, including test results, steps, attachments, traces and the configuration and project metadata needed to render a report later, and packs it into a zip archive. ```ts import { defineConfig } from '@playwright/test'; export default defineConfig({ reporter: process.env.CI ? 'blob' : 'html', }); ``` Or per invocation, `npx playwright test --shard=1/4 --reporter=blob`. Each shard writes one archive into the `blob-report` directory, and the file name carries the shard number so four jobs writing into a shared location do not collide. ## Collecting and merging The pipeline gathers the four archives into one directory and runs the merge once, after every shard has ended: ```bash npx playwright merge-reports --reporter=html ./all-blob-reports ``` The command reads the directory of archives and replays them through the reporter you name, producing one report as if the suite had run on a single machine. Useful details: - `--reporter` accepts the same reporters a run does, so the same archives can produce `html`, `junit`, `list` or `github` output in one pass or in several. - `--config playwright.config.ts` makes the merge reuse the reporter configuration already in the repository instead of restating options on the command line. - The merge is offline and needs no browsers; it only reads archives. ## What survives the merge | Concern | Four HTML reports | Merged from blob | |---|---|---| | Suite totals | four partial counts | one true count | | Traces and attachments | scattered per shard | present in one report | | Flaky classification | per shard only | across the whole run | | Consumable by CI viewers | four artefacts | one artefact | ## Constraints worth stating in an interview 1. **Same version everywhere.** Archives are tied to the Playwright version that wrote them; a suite pinned to 1.63 must produce and merge all of its archives with 1.63. A shard on a different version is the usual cause of a merge that refuses to run. 2. **Merge after, not during.** The merge job must depend on all shard jobs completing, including failed ones, or the report silently misses a quarter of the suite. 3. **Exit codes are separate from reports.** A merged report showing failures does not by itself fail the pipeline; the shard job outcomes still decide that. 4. **Do not use blob locally.** An archive is not readable by a human; keep `html` or `list` for developer runs and switch to `blob` only where sharding happens. ## Applying it to a payroll suite A payroll regression suite split four ways in CI ends with each job running `--reporter=blob`, publishing its archive, and one final job pulling all four archives together and merging them to HTML. Reviewers open a single report where the pay-cycle failure in one shard and the payslip failure in another sit in the same tree, with their traces attached, and the run's totals are the suite's totals rather than one machine's.
- Can you get JUnit XML for the whole run as well as the HTML report from the same shards?Yes. The archives are reporter-agnostic, so the merge job can be run again over the same directory with `--reporter=junit`, or given a reporter list through `--config`. Nothing has to be re-executed in a browser, because merging only replays recorded results.
- One shard job crashed before it wrote its archive. What does the merged report show?Only the shards that produced archives. The merge has no way to know a quarter of the suite is missing, so the report looks complete while under-reporting totals. Guard it in the pipeline: fail the run when the number of collected archives does not match the shard total.
A blob archive is a sealed evidence box rather than a written verdict; you can pool four boxes into one case file, but you cannot pool four verdicts.
saying these in an interview costs you the question
- Thinks per-shard HTML reports can be concatenated
- Believes merge-reports reads the html output directory
- Assumes archives from different Playwright versions merge
- Thinks the merged report loses traces and attachments
- Runs the merge before every shard has finished
- Uses the blob reporter for local developer runs