Browser tests
Debug with traces
Use Playwright traces, screenshots, video, and reports to reconstruct a browser failure before adding retries.
8 minute lesson
A CI browser failure needs evidence because you cannot inspect the original page after the process exits.
Retain a trace on the first retry or failure. The trace viewer shows actions, DOM snapshots, network requests, console output, and timing. Screenshots are useful, but a trace explains how the page reached that state.
Configure traces so routine successful runs stay cheap while the first retry preserves the failed attempt:
import { defineConfig } from '@playwright/test'
export default defineConfig({
retries: process.env.CI ? 1 : 0,
use: { trace: 'on-first-retry' }
})
A retry is diagnostic evidence, not a fix. If the first attempt fails and the retry passes, the run has revealed timing, shared-state, or environment sensitivity. Track that event instead of treating the test as healthy forever.
Read a trace in order. Find the last successful user action, inspect the locator and actionability state of the next one, then compare the DOM snapshot before and after. Check failed or slow network requests and browser console errors. This separates “the button could not be clicked” from “the click worked but the API failed” and “the API worked but the page never rendered the result.”
A screenshot captures one visual moment. It cannot show a request that returned 500, a redirect chain, or an element that was replaced between two actions. Video helps with motion and ordering, while the HTML report groups failures and attachments. Retain the smallest artifact set that answers likely questions, and avoid publishing traces that contain secrets or private test data.
Break a selector deliberately, run with tracing, and open the trace to find the last successful action and current DOM. Then create a server-side 500 and compare the network and console evidence so you can explain why the two failures need different fixes.
Lesson completed