视觉比较

简介

Playwright Test 包含了使用 await expect(page).toHaveScreenshot() 进行截图生成和视觉比较的功能。在第一次执行时,Playwright Test 会生成参考截图。随后的运行将与参考截图进行比较。

example.spec.ts
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.

这是因为还没有黄金文件。此方法会拍摄多个截图,直到两次连续的截图匹配,并将最后一张截图保存到文件系统中。现在,它已经准备好可以被添加到版本控制库中了。

黄金期望文件夹的名称以测试文件的名称开头:

drwxr-xr-x  5 user  group  160 Jun  4 11:46 .
drwxr-xr-x  6 user  group  192 Jun  4 11:45 ..
-rw-r--r--  1 user  group  231 Jun  4 11:16 example.spec.ts
drwxr-xr-x  3 user  group   96 Jun  4 11:46 example.spec.ts-snapshots

快照名称 example-test-1-chromium-darwin.png 由以下几个部分组成:

  • example-test-1.png - 自动生成的快照名称。你也可以通过将快照名称作为 toHaveScreenshot() 方法的第一个参数来指定快照名称:

    await expect(page).toHaveScreenshot('landing.png');
  • chromium-darwin - 浏览器名称和平台。由于不同的渲染、字体等因素,浏览器和平台的截图会有所不同,因此你需要为它们准备不同的快照。如果在配置文件中使用了多个项目,项目名称会替代 chromium

快照名称和路径可以通过 Playwright 配置中的 snapshotPathTemplate 来进行配置。

更新截图

有时你需要更新参考截图,例如页面发生了变化。可以使用 --update-snapshots 标志来进行更新。

npx playwright test --update-snapshots

请注意,snapshotName 也接受一个路径段数组来指定快照文件的路径,例如:

expect().toHaveScreenshot(['relative', 'path', 'to', 'snapshot.png']);

然而,这个路径必须保持在每个测试文件的 snapshots 目录内(即 a.spec.js-snapshots),否则会抛出错误。

选项

maxDiffPixels

Playwright Test 使用 pixelmatch 库,你可以传递各种选项来修改其行为:

example.spec.ts
import { test, expect } from '@playwright/test';

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

如果你希望在项目中的所有测试中共享默认值,可以在 Playwright 配置文件中进行指定,无论是全局设置还是每个项目单独设置:

playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
  expect: {
    toHaveScreenshot: { maxDiffPixels: 100 },
  },
});

stylePath

你可以在截图时应用自定义样式表。这允许过滤掉动态或易变的元素,从而提高截图的确定性。

screenshot.css
iframe {
  visibility: hidden;
}
example.spec.ts
import { test, expect } from '@playwright/test';

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

如果你希望在项目中的所有测试中共享默认值,可以在 Playwright 配置文件中进行指定,无论是全局设置还是每个项目单独设置:

playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
  expect: {
    toHaveScreenshot: {
      stylePath: './screenshot.css'
    },
  },
});

非图像快照

除了截图,你还可以使用 expect(value).toMatchSnapshot(snapshotName) 来比较文本或任意二进制数据。Playwright Test 会自动检测内容类型,并使用适当的比较算法。

下面是比较文本内容的例子:

example.spec.ts
import { test, expect } from '@playwright/test';

test('example test', async ({ page }) => {
  await page.goto('https://playwright.dev');
  expect(await page.textContent('.hero__title')).toMatchSnapshot('hero.txt');
});

快照会存储在测试文件旁边的单独目录中。例如,my.spec.ts 文件会在 my.spec.ts-snapshots 目录中生成并存储快照。你应该将此目录提交到版本控制中(如 git),并审核其中的任何更改。