跳到主要内容

快照测试

概述

使用 Playwright 的快照测试,您可以针对预定义的快照模板断言页面的可访问性树。

await page.goto('https://playwright.net.cn/');
await expect(page.getByRole('banner')).toMatchAriaSnapshot(`
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
`);

断言测试 vs 快照测试

快照测试和断言测试在测试自动化中服务于不同的目的

断言测试

断言测试是一种有针对性的方法,您可以在其中断言元素或组件的特定值或条件。例如,使用 Playwright,expect(locator).toHaveText() 验证元素是否包含预期的文本,而 expect(locator).toHaveValue() 确认输入字段具有预期的值。断言测试是具体的,通常检查元素或属性的当前状态是否符合预期的、预定义的状态。它们非常适用于可预测的、单值检查,但在测试更广泛的结构或变化时范围有限。

优点

  • 清晰:测试意图明确,易于理解。
  • 特异性:测试专注于功能的特定方面,使其对无关的更改更具鲁棒性。
  • 调试:失败提供有针对性的反馈,直接指向有问题的地方。

缺点

  • 对复杂输出冗长:为复杂数据结构或大型输出编写断言可能既麻烦又容易出错。
  • 维护开销:随着代码的发展,手动更新断言可能非常耗时。

快照测试

快照测试捕获元素、组件或数据在给定时刻的整体状态的“快照”或表示,然后保存以供将来比较。当重新运行测试时,当前状态与快照进行比较,如果存在差异,测试将失败。这种方法对于复杂或动态的结构特别有用,手动断言每个细节会非常耗时。快照测试比断言测试更广泛、更全面,允许您随着时间的推移跟踪更复杂的更改。

优点

  • 简化复杂输出:例如,使用传统断言测试 UI 组件的渲染输出可能很繁琐。快照捕获整个输出以便于比较。
  • 快速反馈循环:开发者可以轻松发现输出中意外的更改。
  • 促进一致性:有助于在代码演变时保持一致的输出。

缺点

  • 过度依赖:可能会倾向于接受对快照的更改而不完全理解它们,这可能隐藏 bug。
  • 粒度:当出现差异时,大型快照可能难以解释,特别是如果微小的更改影响到输出的大部分时。
  • 适用性:不适合高度动态的内容,其中输出频繁或不可预测地变化。

何时使用

  • 快照测试非常适合
    • 整个页面和组件的 UI 测试。
    • 复杂 UI 组件的广泛结构检查。
    • 对结构很少更改的输出进行回归测试。
  • 断言测试非常适合
    • 核心逻辑验证。
    • 计算值测试。
    • 需要精确条件的细粒度测试。

通过结合用于广泛结构检查的快照测试和用于特定功能的断言测试,您可以实现全面的测试策略。

Aria 快照

在 Playwright 中,aria 快照提供了页面可访问性树的 YAML 表示。这些快照可以存储起来,以后进行比较,以验证页面结构是否保持一致或满足定义的预期。

YAML 格式描述了页面上可访问元素的层次结构,详细说明了角色属性文本内容。其结构遵循树状语法,其中每个节点表示一个可访问元素,缩进表示嵌套元素。

树中的每个可访问元素都表示为一个 YAML 节点

- role "name" [attribute=value]
  • role:指定元素的 ARIA 或 HTML 角色(例如,headinglistlistitembutton)。
  • "name":元素的易访问名称。带引号的字符串表示精确值,/patterns/ 用于正则表达式。
  • [attribute=value]:方括号中的属性和值代表特定的 ARIA 属性,例如 checkeddisabledexpandedlevelpressedselected

这些值派生自 ARIA 属性或基于 HTML 语义计算。要检查页面的可访问性树结构,请使用 Chrome DevTools 的可访问性选项卡

快照匹配

Playwright 中的 expect(locator).toMatchAriaSnapshot() 断言方法将定位器范围内的可访问结构与预定义的 aria 快照模板进行比较,有助于根据测试要求验证页面的状态。

对于以下 DOM

<h1>title</h1>

您可以使用以下快照模板进行匹配

await expect(page.locator('body')).toMatchAriaSnapshot(`
- heading "title"
`);

匹配时,快照模板与页面的当前可访问性树进行比较

  • 如果树结构与模板匹配,则测试通过;否则,它将失败,表明预期的和实际的可访问性状态之间存在不匹配。
  • 比较区分大小写并折叠空白字符,因此忽略缩进和换行符。
  • 比较区分顺序,这意味着快照模板中元素的顺序必须与页面可访问性树中的顺序匹配。

部分匹配

您可以通过省略属性或易访问名称对节点执行部分匹配,从而验证可访问性树的特定部分而无需完全匹配。这种灵活性对于动态或不相关的属性很有帮助。

<button>Submit</button>

aria 快照

- button

在此示例中,按钮的角色被匹配,但未指定易访问名称("Submit"),因此无论按钮的标签是什么,测试都会通过。


对于具有 checkeddisabled 等 ARIA 属性的元素,省略这些属性允许部分匹配,只关注角色和层次结构。

<input type="checkbox" checked>

部分匹配的 aria 快照

- checkbox

在此部分匹配中,忽略了 checked 属性,因此无论复选框的状态如何,测试都会通过。


同样,您可以通过省略特定的列表项或嵌套元素来部分匹配列表或组中的子项。

<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

部分匹配的 aria 快照

- list
- listitem: Feature B

部分匹配使您能够创建灵活的快照测试,验证重要的页面结构而无需强制执行特定内容或属性。

严格匹配

默认情况下,将匹配包含子项子集的模板

<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

部分匹配的 aria 快照

- list
- listitem: Feature B

可以使用 /children 属性来控制子元素如何匹配

  • contain (默认):如果所有指定的子项都按顺序存在,则匹配
  • equal:如果子项与指定的列表完全按顺序匹配,则匹配
  • deep-equal:如果子项与指定的列表完全按顺序匹配,包括嵌套子项,则匹配
<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>

由于模板中没有 Feature C,aria 快照将失败

- list
- /children: equal
- listitem: Feature A
- listitem: Feature B

使用正则表达式匹配

正则表达式允许对具有动态或可变文本的元素进行灵活匹配。易访问名称和文本可以支持 regex 模式。

<h1>Issues 12</h1>

带正则表达式的 aria 快照

- heading /Issues \d+/

生成快照

在 Playwright 中创建 aria 快照有助于确保和维护应用程序的结构。您可以根据测试设置和工作流程以各种方式生成快照。

使用 Playwright 代码生成器生成快照

如果您正在使用 Playwright 的 代码生成器,通过其交互式界面可以简化 aria 快照的生成

  • “断言快照”操作:在代码生成器中,您可以使用“断言快照”操作为选定的元素自动创建快照断言。这是捕获 aria 快照作为录制测试流程的一部分的快速方法。
  • “Aria 快照”选项卡:代码生成器界面中的“Aria 快照”选项卡直观地显示了选定定位器的 aria 快照,让您可以探索、检查和验证元素的角色、属性和易访问名称,以帮助快照创建和审查。

使用 @playwright/test--update-snapshots 标志更新快照

使用 Playwright 测试运行器 (@playwright/test) 时,您可以使用 --update-snapshots 标志(简写为 -u)自动更新快照。

使用 --update-snapshots 标志运行测试将更新不匹配的快照。匹配的快照将不会被更新。

npx playwright test --update-snapshots

当应用程序结构更改需要新的快照作为基线时,更新快照很有用。请注意,Playwright 将等待测试运行器配置中指定的最大 expect 超时,以确保页面在拍摄快照之前处于稳定状态。如果在生成快照时测试达到超时,可能需要调整 --timeout

用于生成快照的空模板

在断言中传递空字符串作为模板将即时生成快照

await expect(locator).toMatchAriaSnapshot('');

请注意,Playwright 将等待测试运行器配置中指定的最大 expect 超时,以确保页面在拍摄快照之前处于稳定状态。如果在生成快照时测试达到超时,可能需要调整 --timeout

快照补丁文件

更新快照时,Playwright 会创建捕获差异的补丁文件。这些补丁文件可以进行审查、应用和提交到源代码管理,从而使团队能够跟踪结构更改并确保更新与应用程序要求一致。

可以使用 --update-source-method 标志更改源代码的更新方式。有几个可用选项

  • “patch” (默认):生成可使用 git apply 应用于源代码的统一 diff 文件。
  • “3way”:在源代码中生成合并冲突标记,允许您选择是否接受更改。
  • “overwrite”:使用新的快照值覆盖源代码。
npx playwright test --update-snapshots --update-source-method=3way

将快照作为单独的文件

要将快照存储在单独的文件中,请使用 toMatchAriaSnapshot 方法和 name 选项,并指定 .aria.yml 文件扩展名。

await expect(page.getByRole('main')).toMatchAriaSnapshot({ name: 'main.aria.yml' });

默认情况下,测试文件 example.spec.ts 中的快照会放在 example.spec.ts-snapshots 目录中。由于快照在不同浏览器中应相同,即使使用多个浏览器进行测试,也只保存一个快照。如果需要,您可以使用以下配置自定义快照路径模板

export default defineConfig({
expect: {
toMatchAriaSnapshot: {
pathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
},
},
});

使用 Locator.ariaSnapshot 方法

locator.ariaSnapshot() 方法允许您以编程方式在定位器的范围内创建可访问元素的 YAML 表示,这对于在测试执行期间动态生成快照特别有用。

示例:

const snapshot = await page.locator('body').ariaSnapshot();
console.log(snapshot);

此命令以 YAML 格式输出指定定位器范围内的 aria 快照,您可以根据需要对其进行验证或存储。

可访问性树示例

带有级别属性的标题

标题可以包含一个 level 属性,指示其标题级别。

<h1>Title</h1>
<h2>Subtitle</h2>

aria 快照

- heading "Title" [level=1]
- heading "Subtitle" [level=2]

文本节点

独立的或描述性的文本元素显示为文本节点。

<div>Sample accessible name</div>

aria 快照

- text: Sample accessible name

内联多行文本

多行文本,如段落,在 aria 快照中被规范化。

<p>Line 1<br>Line 2</p>

aria 快照

- paragraph: Line 1 Line 2

链接显示其文本或由伪元素组成的内容。

<a href="#more-info">Read more about Accessibility</a>

aria 快照

- link "Read more about Accessibility"

文本框

类型为 text 的输入元素显示其 value 属性内容。

<input type="text" value="Enter your name">

aria 快照

- textbox: Enter your name

带项目的列表

有序和无序列表包含其列表项。

<ul aria-label="Main Features">
<li>Feature 1</li>
<li>Feature 2</li>
</ul>

aria 快照

- list "Main Features":
- listitem: Feature 1
- listitem: Feature 2

分组元素

组捕获嵌套元素,例如带摘要内容的 <details> 元素。

<details>
<summary>Summary</summary>
<p>Detail content here</p>
</details>

aria 快照

- group: Summary

属性和状态

常用的 ARIA 属性,如 checkeddisabledexpandedlevelpressedselected,表示控件状态。

checked 属性的复选框

<input type="checkbox" checked>

aria 快照

- checkbox [checked]

pressed 属性的按钮

<button aria-pressed="true">Toggle</button>

aria 快照

- button "Toggle" [pressed=true]