100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Reporters and HTML Reports

How Playwright's built-in reporters work, how to configure and combine them, and how to build a custom reporter for bespoke workflows.

Scaling & CIBeginner8 min readJul 10, 2026
Analogies

Playwright's Built-in Reporters

Playwright ships several built-in reporters selectable via the reporter option: 'list' prints one line per test as it runs (the default for local interactive terminals), 'dot' prints a single character per test for compact CI logs, 'json' and 'junit' produce machine-readable output for integrating with dashboards or tools like Jenkins, and 'html' generates a self-contained, browsable report with screenshots, traces, and video attached to each test result. Choosing the right reporter is about audience: humans watching a terminal want 'list', CI log parsers want 'json' or 'junit', and anyone debugging a failure after the fact wants 'html'.

🏏

Cricket analogy: Choosing a reporter is like choosing how a match is covered: a radio commentator gives a rapid ball-by-ball 'dot' style call, while a full TV broadcast with replays is the detailed 'html' equivalent for later review.

The HTML Reporter in Depth

The HTML reporter produces a static site under playwright-report/ by default, showing a filterable dashboard of passed, failed, flaky, and skipped tests, and clicking into any test reveals step-by-step execution with timestamps, network requests, console logs, and—if trace: 'on' or 'on-first-retry' was configured—a full Playwright Trace Viewer embedded inline letting you scrub through a timeline of DOM snapshots and actions. Running npx playwright show-report serves this folder locally and auto-opens a browser tab, which is convenient locally but should be disabled on CI since CI runners have no browser to open and the command would otherwise hang or error.

🏏

Cricket analogy: The HTML report's embedded trace viewer is like a third-umpire review screen letting you scrub frame by frame through a run-out at the crease instead of just reading the final 'out' verdict.

typescript
// playwright.config.ts
export default defineConfig({
  reporter: [
    ['html', { open: process.env.CI ? 'never' : 'on-failure', outputFolder: 'playwright-report' }],
  ],
  use: {
    trace: 'on-first-retry',
  },
});

Combining Multiple Reporters

You can configure multiple reporters simultaneously by passing an array of [name, options] tuples to the reporter property, e.g. reporter: [['dot'], ['html', {open: 'never'}], ['junit', {outputFile: 'results.xml'}]], so a single test run simultaneously prints compact progress to the CI log, writes a browsable HTML report as an artifact, and emits a JUnit XML file that your CI platform's test-results UI can parse to show pass/fail trends over time. This is standard practice in mature pipelines because no single reporter format satisfies both human debugging and automated dashboarding needs.

🏏

Cricket analogy: Running dot, html, and junit reporters together is like a match producing a live radio commentary, a full TV highlights package, and an official scorecard PDF all from the same innings simultaneously.

The Trace Viewer embedded in the HTML report lets you inspect every action's before/after DOM snapshot, network calls, and console output on a scrubbable timeline — it's often faster to diagnose a CI-only failure this way than by adding print statements and re-running the pipeline.

Custom Reporters

For bespoke needs—posting results to Slack, writing to a custom database, or annotating pull requests—you implement the Reporter interface, overriding lifecycle hooks like onBegin, onTestEnd(test, result), and onEnd(result) to receive structured data about every test as it completes, then reference your custom reporter file's path directly in the reporter array. Because onTestEnd fires once per attempt including retries, a naive custom reporter that just counts calls will over-report failures unless it checks result.retry to only count the final attempt per test.

🏏

Cricket analogy: A custom reporter posting results to Slack is like a franchise's dedicated stats analyst who feeds live win-probability numbers to the dugout during the match instead of waiting for the post-match report.

Always disable auto-opening the HTML report on CI with { open: 'never' }. Without it, npx playwright test (or a subsequent show-report call) can attempt to launch a browser window on a headless runner and hang the job or throw an unhelpful error.

  • 'list', 'dot', 'json', 'junit', and 'html' are Playwright's built-in reporters, each suited to a different audience.
  • The HTML report is a static, filterable dashboard with an embedded Trace Viewer for step-by-step debugging.
  • Set { open: 'never' } on CI to prevent the HTML reporter from trying to auto-launch a browser.
  • Multiple reporters can run in the same test execution via an array of [name, options] tuples.
  • JUnit XML output integrates with CI platforms' native test-result dashboards and trend tracking.
  • Custom reporters implement onBegin, onTestEnd, and onEnd to hook into structured per-test data.
  • onTestEnd fires per attempt, so custom reporters must check result.retry to avoid double-counting.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#PlaywrightStudyNotes#TestingQA#ReportersAndHTMLReports#Reporters#HTML#Reports#Playwright#WebDevelopment#StudyNotes#SkillVeris