Visual regression testing for web interfaces: choose capture points and viewports, make captures deterministic, set diff budgets that catch small real changes, triage flaky diffs from fonts and animation, review and approve baseline updates, and wire the check into CI in stages. Ships a working Python pixel-diff tool with exit codes, masks and region counting, Playwright and BackstopJS setups, and a worked baseline update. Use when a layout breaks unnoticed, when screenshot tests flake, or when setting up visual testing from scratch.
./install.sh visual-regression-testingname: visual_regression_testing description: "Visual regression testing for web interfaces: choose capture points and viewports, make captures deterministic, set diff budgets that catch small real changes, triage flaky diffs from fonts and animation, review and approve baseline updates, and wire the check into CI in stages. Ships a working Python pixel-diff tool with exit codes, masks and region counting, Playwright and BackstopJS setups, and a worked baseline update. Use when a layout breaks unnoticed, when screenshot tests flake, or when setting up visual testing from scratch."
Catch visual breaks that functional tests walk past: a button that moved off screen, a colour that changed by accident, text that now overflows its card. The method is simple on paper. Capture a screenshot of a known good state (the baseline), capture the same view later, diff the two, and have a person judge the diff. The work that makes it useful sits around that loop: choosing what to capture, making captures repeatable, keeping baselines honest, and putting the check in CI at a strength the team can live with.
This skill ships working code, not just advice: bin/vrt_diff.py compares two PNGs and reports diff pixels, diff ratio, connected diff regions, and masked pixels, with exit codes designed for CI. Playwright and BackstopJS setups and a fully worked baseline update live in examples/.
toHaveScreenshot() captures and compares in one assertion, with baselines stored beside the test file. BackstopJS if you want config-driven page scenarios without a test suite. A hosted service (Percy or Applitools) if cross-browser rendering and a hosted review queue are worth paying for. The shipped diff tool fits static captures and non-Playwright stacks, and teaches the budget ideas every engine uses.references/capture-and-viewports.md. Start with money paths, shared components, and the states where layout breaks hide (empty, error, long text, many items). Two viewports by default, desktop 1440 by 900 and phone 390 by 844, device pixel ratio pinned to 1. Grow the list from visual bugs that escaped, not from coverage pride. A first suite of 10 to 30 captures that reviewers actually read beats a large suite they skim.document.fonts.ready), for images to decode, and for a ready marker the page sets itself. Freeze animation in two layers: the tool option plus the screenshot stylesheet in examples/playwright/screenshot.css. Pin time and seed the data. Clear hover and hide the caret. The Playwright setup in examples/playwright/ wires all of this.maxDiffPixelRatio so the budget scales with image size, and add a region cap where you can, because a small real change can be a tiny ratio and one clear region. Start near a 0.1 percent ratio, then tune from your own run history. Never tune a budget to make a specific failure pass without naming the change that caused it.example-test-1-chromium-darwin.png style names carry browser and platform for a reason. In BackstopJS, backstop reference captures and backstop test compares. Commit baselines to version control, in the same change as the code they describe once the suite is running. A baseline captured on a half-finished branch poisons every later run.references/flake-triage.md, in order: environment, viewport, fonts, timing, dynamic content, anti-aliasing. Most false diffs are capture faults. Fix the capture. Mask only regions that are dynamic by design (a live clock, an ad slot), record the reason in the test, and keep masked area visible in the report: the shipped tool counts masked pixels on every run. Never approve a flaky capture as the new baseline.references/review-and-ci.md. Read baseline, current, and diff images. Write down what changed and which ticket intended it. Regenerate only approved captures (Playwright --update-snapshots scoped to the spec, BackstopJS backstop approve, or promote the reviewed PNG with the shipped tool), log the approval with the template in examples/worked-example/approval-log.md, commit baselines with the causing code, and re-run green before merging. The worked example in examples/worked-example/ walks one real change, one masked clock change, and one baseline promotion end to end, with the tool output quoted.A visual regression setup or run report contains all six:
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.