Getting Started

Your First Visual Regression Test in 10 Minutes

Visual regression testing catches unintended UI changes by comparing screenshots. In this guide you will go from zero to a working Playwright visual test, learn how diffs work, and set up CI so regressions never reach production.

Before You Start

Prerequisites

  • Node.js 18 or later installed
  • A web app running locally (any framework)
  • Basic comfort with the terminal
  • No Playwright experience required

Step 1: Install Playwright

Playwright ships with built-in screenshot comparison. One command gets you everything: the test runner, browser binaries, and config scaffolding.

terminal

This creates a playwright.config.ts file and a tests/ directory. The config is where you control screenshot thresholds, browser selection, and viewport sizes.

Step 2: Write Your First Screenshot Test

A visual regression test navigates to a page and calls toHaveScreenshot(). Playwright handles the rest: capturing the image, storing the baseline, and comparing future runs pixel by pixel.

tests/visual.spec.ts

The maxDiffPixelRatio option tells Playwright to allow up to 1% of pixels to differ. This accounts for minor rendering variations across operating systems without letting real regressions through.

Step 3: Generate the Baseline

The first time you run the test it will fail because no baseline exists yet. Playwright tells you to update snapshots.

terminal
Expected output

Playwright saves the baseline image to a tests/visual.spec.ts-snapshots/ directory. Commit this directory to version control so every team member compares against the same baseline.

Step 4: Detect a Regression

Change something in your UI (swap a color, move a button, change font size) and run the test again without the update flag.

terminal
Failure output

Playwright generates three files in the test results: the expected image, the actual image, and a diff highlighting every changed pixel. Open the diff to see exactly what changed.

Step 5: Test Specific Components

Full-page screenshots are a good starting point, but they break often because any change anywhere on the page triggers a diff. For more targeted tests, screenshot individual elements.

tests/components.spec.ts

Element-level screenshots are less noisy than full-page captures. When the footer changes, your navbar test stays green.

Step 6: Handle Dynamic Content

Dates, avatars, ads, and animations will cause false failures if you screenshot them as-is. Playwright lets you mask or hide dynamic elements before capturing.

tests/dashboard.spec.ts

Masked elements are replaced with a solid color block in the screenshot. The test compares everything else normally. This is the single most important technique for keeping visual tests stable.

Step 7: Add CI Integration

Visual tests should run on every pull request. GitHub Actions works well because Playwright can install browsers in the CI environment.

.github/workflows/visual-regression.yml

When a test fails in CI, the diff images upload as artifacts. Reviewers can download them to see exactly what changed before approving the PR.

Mistakes Beginners Make (and How to Avoid Them)

Running on different operating systems

Font rendering differs between macOS, Windows, and Linux. Generate baselines on the same OS your CI uses (usually Linux). Use Docker or generate baselines in CI itself.

Screenshotting before the page is ready

Images, fonts, and animations that have not finished loading produce different screenshots every run. Always call waitForLoadState('networkidle') or wait for specific elements before capturing.

Setting the threshold too tight

A 0% pixel diff threshold sounds safe but generates constant false positives from anti-aliasing differences. Start at 1% and tighten only if you find real regressions slipping through.

Never updating baselines

When you intentionally change the UI, update baselines with --update-snapshots. Leaving stale baselines trains the team to ignore failures.

Skip the boilerplate

Assrt generates real Playwright visual tests from plain English descriptions. Open source, self-hosted, no vendor lock-in.

Get Started

Related Guides