首页 / Playwright 入门教程 / 视觉对比测试 Visual Comparisons

Playwright 入门教程

视觉对比测试 Visual Comparisons

本教程共 59 篇 · 第 48 篇 · 更新于 2026-08-04 · 约 7 分钟阅读

Playwright视觉对比VisualComparisonstoHaveScreenshot视觉回归基准图maxDiffPixels

本节目标:学完你能用一张截图当「标准答案」,之后每次跑测试自动比对新旧图,发现页面长相变了。

普通的断言查的是文字、数值。可页面「长得对不对」光看文字查不出来。Visual Comparison(视觉对比)就是让 Playwright 帮你「看」一眼:截图存成基准,下次跑再截一次,逐像素比对。

它怎么工作

核心方法是 expect(page).toHaveScreenshot()。第一次跑没有基准图,它会先生成一张,存进仓库。之后再跑,就拿新图跟基准图比。

import { test, expect } from '@playwright/test';

test('example test', async ({ page }) => {
  await page.goto('https://playwright.dev');
  await expect(page).toHaveScreenshot();
});

第一次跑会发生什么

你第一次执行,终端会提示「没有基准图,先写一份」:

Error: A snapshot doesn't exist at example.spec.ts-snapshots/example-test-1-chromium-darwin.png, writing actual.

它连续截几张、直到两张一致,再把最后一张存盘。这份图要提交进 git,当标准答案。

Warning

不同操作系统、不同浏览器、甚至插不插电源,渲染都可能略有差异。想结果稳,就在生成基准的同一环境里跑对比测试。

基准图的命名

基准图默认放在 你的测试文件-snapshots/ 目录里。文件名带两部分:

  • example-test-1.png:自动起的快照名。你也可以自己起名:toHaveScreenshot('landing.png')
  • chromium-darwin:浏览器名加平台。不同浏览器、平台截图不一样,要各存一份。配置里用了多个 project 时,这里显示的是项目名。

想要 WebP 格式(同样无损、更小),把扩展名写成 .webp

await expect(page).toHaveScreenshot('landing.webp');
Tip

嫌默认目录结构别扭,可以在配置里用 snapshotPathTemplate 自定义基准图的存放路径和命名规则。

更新基准图

页面真的改版了,旧基准就该换。用这个命令重生成:

npx playwright test --update-snapshots
Tip

更新前先 review 差异。别脑子一热全量更新,把真回归也顺手盖掉了。

容忍一点点差异

像素不可能 100% 一样。Playwright 底层用的是 pixelmatch 这个库,用 maxDiffPixels 设允许的最大不同像素数:

await expect(page).toHaveScreenshot({ maxDiffPixels: 100 });

想全项目共用一个值,写进配置:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  expect: {
    toHaveScreenshot: { maxDiffPixels: 100 },
  },
});

过滤掉会动的元素

有些东西每回不一样:广告 iframe、时间戳、动画。用 stylePath 套一张样式表,把它们藏起来,截图就稳定了。

/* screenshot.css */
iframe {
  visibility: hidden;
}
import { test, expect } from '@playwright/test';
import path from 'path';

test('example test', async ({ page }) => {
  await page.goto('https://playwright.dev');
  await expect(page).toHaveScreenshot({
    stylePath: path.join(__dirname, 'screenshot.css'),
  });
});

不止比图片

除了整页截图,还能比纯文本或任意二进制数据。Playwright 会自动判断内容类型,选合适的比对算法:

import { test, expect } from '@playwright/test';

test('标题文案没变', async ({ page }) => {
  await page.goto('https://playwright.dev');
  expect(await page.textContent('.hero__title')).toMatchSnapshot('hero.txt');
});

快照同样存在测试文件旁边的 *-snapshots 目录,记得提交进版本库。这类非图片快照,第 49 章还会细讲。

什么时候用它

视觉对比适合「整页或整块 UI 长相基本不变」的场景,比如组件库、官网首屏。内容天天变的动态页面别硬上,否则天天误报。

一句话:视觉对比是「看长相」的测试,基准图进 git,改版用 --update-snapshots 重生成。

小结

视觉对比就是「看长相」的测试,基准图锁进 git,改版用 —update-snapshots 重生成。它适合 UI 长得基本不变的场景,动态内容多的页面别硬上,否则天天误报。maxDiffPixels 和 stylePath 是稳定截图的两大法宝,一个容忍像素差,一个藏掉会动的东西。