Playwright Trace Viewer, Reports & Debugging
A failing test is only useful if you can see why it failed. Playwright ships everything needed for that: reporters for humans and CI, a Trace Viewer that replays every step of a run, UI mode and the Inspector for step-by-step debugging, and automatic screenshots and videos. This guide shows how to set them up in one config and which tool to reach for in each situation.
A Working Configuration
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
retries: process.env.CI ? 1 : 0,
reporter: [
['list'], // console output
['html', { open: 'never', outputFolder: 'playwright-report' }],
['junit', { outputFile: 'results/junit.xml' }], // for Jenkins / Azure DevOps / GitLab
],
use: {
baseURL: 'https://www.saucedemo.com',
trace: 'on-first-retry', // record a trace when a failed test is retried
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
});
This is the typical setup: humans read the HTML report, CI reads the JUnit XML, and every failure comes with a trace, screenshot and video.
Reporters
| Reporter | Output | Typical use |
|---|---|---|
list |
One line per test in the console | Local runs (the default locally) |
line / dot |
Compact console output | Large suites, CI logs |
html |
Interactive report with steps, errors, attachments and traces | Debugging and sharing results |
junit |
JUnit XML | CI test-result trends |
json |
Machine-readable results | Custom dashboards |
blob |
Mergeable results | Combining sharded CI runs into one report |
Allure and other third-party reporters plug in the same way. Open the HTML report with:
npx playwright show-report
Interview answer: "Playwright has built-in list, line, dot, HTML, JSON, JUnit and blob reporters, and you can run several at once. We used the HTML report for debugging — it shows each step, the error, screenshots, videos and the trace — and JUnit XML so Jenkins could track results over time."
Make Reports Readable: Steps and Attachments
import { test, expect } from '@playwright/test';
test('checkout shows the order summary', async ({ page }, testInfo) => {
await test.step('log in', async () => {
await page.goto('/');
await page.locator('#user-name').fill('standard_user');
await page.locator('#password').fill('secret_sauce');
await page.locator('#login-button').click();
});
await test.step('add a product to the cart', async () => {
await page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click();
await expect(page.locator('[data-test="shopping-cart-badge"]')).toHaveText('1');
});
await testInfo.attach('cart-state', {
body: JSON.stringify({ items: 1 }, null, 2),
contentType: 'application/json',
});
// await page.pause(); // uncomment to stop here and open the Inspector
});
test.step groups actions into named steps in the report and trace, so a failure reads "failed in add a product to the cart" instead of line 14. testInfo.attach adds any evidence — API responses, logs, files.
Trace Viewer ⭐
A trace is a recording of a test run: every action, a DOM snapshot before and after each step, console logs, network requests and the source line. The Trace Viewer replays it like CCTV footage after an incident — you can hover over each step and see exactly what the page looked like.
| Setting | Records | Use |
|---|---|---|
'off' |
Nothing | Fastest |
'on' |
Every test | Short debugging sessions only — heavy |
'retain-on-failure' |
Every test, keeps failures only | When retries are disabled |
'on-first-retry' |
Only the first retry of a failed test | ⭐ The usual CI setting |
npx playwright test --trace on # force tracing for one run
npx playwright show-trace test-results/…/trace.zip # open a trace locally
You can also drag a trace.zip into trace.playwright.dev — it opens in the browser without installing anything, which is handy for traces downloaded from CI.
What the Trace Viewer shows
- Actions timeline with duration of each step.
- Before / after DOM snapshots — inspect the page as it was.
- Locator used and why an action waited or failed.
- Console messages and errors.
- Network requests with status and timing.
- Source — the test line for each action.
Debugging Tools — Which to Use When
| Situation | Tool | How |
|---|---|---|
| Writing or fixing a test locally | UI mode | npx playwright test --ui — watch mode, time-travel through steps, pick locators |
| Stepping through a test action by action | Debug mode + Inspector | npx playwright test login.spec.ts --debug (or PWDEBUG=1) |
| Stopping at one specific point | page.pause() |
Add await page.pause(); run headed |
| Just watching the browser | Headed mode | npx playwright test --headed |
| Finding a locator | Codegen / Inspector picker | npx playwright codegen https://www.saucedemo.com |
| A failure that only happened in CI | Trace Viewer | Download the trace artifact and open it |
| Watching slowly | Slow motion | use: { launchOptions: { slowMo: 500 } } |
The VS Code extension combines several of these: run a single test, set breakpoints and pick locators from the editor.
page.pause() and the Inspector
page.pause() is the pause button: execution stops and the Playwright Inspector opens, where you can step over actions, try locators live and resume. Remove it before committing — in a headless CI run there's no Inspector to resume from.
Screenshots and Videos
| Option | Values | Recommended |
|---|---|---|
screenshot |
'off', 'on', 'only-on-failure' |
'only-on-failure' |
video |
'off', 'on', 'retain-on-failure', 'on-first-retry' |
'retain-on-failure' or 'on-first-retry' |
Screenshots, videos and traces are saved per test in test-results/ and appear in the HTML report. For a manual screenshot: await page.screenshot({ path: 'cart.png', fullPage: true }), or of one element: await locator.screenshot({ path: 'badge.png' }).
Debugging a CI-Only Failure
- Publish
playwright-report/andtest-results/as build artifacts (and the JUnit XML to the CI test view). - Open the failing test in the HTML report — read the error and the failed step.
- Open its trace: compare the DOM snapshot at the failing step with what you expected.
- Check the Network tab in the trace for failed or slow API calls, and the Console for errors.
- Reproduce locally with the same browser, viewport and
--headedor--ui.
Most CI-only failures turn out to be timing (fixed with web-first assertions — see Playwright Auto-Wait), test data, or environment differences.
Coming from Selenium, where you had to build screenshots and logging yourself? Compare the equivalents in the Selenium ⇄ Playwright ⇄ Cypress Translator.
From Real Projects
I've built my automation skills on Selenium with Java and TestNG, and that background maps well onto Playwright: page classes become page objects, TestNG groups and parallel runs become projects and workers, and explicit waits become auto-waiting and web-first assertions. If you're coming from Selenium too, focus on those differences first. Testing Testsigma — a platform where users write automated tests in plain English — meant thinking like its users, who are testers themselves. Open the trace for every flaky failure before changing the test.
FAQs
What reporters does Playwright support?
Built in: list, line, dot, HTML, JSON, JUnit and blob. Several can run at once, and third-party reporters such as Allure plug in the same way.
What is the Playwright Trace Viewer?
A tool that replays a recorded test run — actions, DOM snapshots, console, network and source — so you can see exactly why a test failed.
Which trace setting should I use in CI?
'on-first-retry' with retries enabled, or 'retain-on-failure' without retries. Avoid 'on' for full suites — it's heavy.
How do you open a trace?
npx playwright show-trace path/to/trace.zip, from the HTML report, or by dropping the file into trace.playwright.dev.
What is page.pause()?
A call that pauses the test and opens the Playwright Inspector for step-by-step debugging in headed mode.
--debug or UI mode?
UI mode (--ui) for writing and exploring tests with time-travel; --debug for stepping through a specific test in the Inspector.