跳至主要内容

快照测试

概述

通过Playwright的快照测试功能,您可以将页面的无障碍访问树与预定义的快照模板进行比对断言。

await page.goto('https://playwright.dev/');
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组件的渲染输出可能很繁琐。快照功能可以捕获整个输出以便于比较。
  • 快速反馈循环: 开发者可以轻松发现输出中的意外变化。
  • 鼓励一致性: 帮助在代码演进过程中保持一致的输出。

缺点

  • 过度依赖: 人们可能会在未完全理解的情况下接受快照变更,这可能会掩盖潜在的错误。
  • 粒度: 当出现差异时,大型快照可能难以解读,特别是当微小改动影响大部分输出内容时。
  • 适用性: 不适合输出频繁或不可预测变化的高度动态内容。

何时使用

  • Snapshot testing is ideal for:
    • 整页和组件的UI测试。
    • 针对复杂UI组件的广泛结构检查。
    • 针对结构很少变化的输出进行回归测试。
  • Assertion testing is ideal for:
    • 核心逻辑验证。
    • 计算值测试。
    • 需要精确条件的细粒度测试。

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

Aria 快照

在Playwright中,aria快照提供了页面无障碍树的YAML表示形式。这些快照可以存储并在之后进行比较,以验证页面结构是否保持一致或符合定义的预期。

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

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

- role "name" [attribute=value]
  • role: Specifies the ARIA or HTML role of the element (e.g., heading, list, listitem, button).
  • "name": 元素的可访问名称。引号内的字符串表示精确值,/patterns/用于正则表达式。
  • [attribute=value]: 方括号中的属性和值表示特定的ARIA属性,例如checkeddisabledexpandedlevelpressedselected

These values are derived from ARIA attributes or calculated based on HTML semantics. To inspect the accessibility tree structure of a page, use the Chrome DevTools Accessibility Pane.

快照匹配

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

对于以下DOM:

<h1>title</h1>

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

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

在匹配时,快照模板将与页面的当前无障碍树进行比较:

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

部分匹配

您可以通过省略属性或可访问名称来对节点进行部分匹配,从而无需完全匹配即可验证可访问性树的特定部分。这种灵活性对于动态或无关紧要的属性非常有用。

<button>Submit</button>

aria 快照

- button

在这个例子中,按钮角色匹配成功,但无障碍名称("Submit")未被指定,这使得无论按钮标签是什么,测试都能通过。


对于具有ARIA属性(如checkeddisabled)的元素,省略这些属性允许部分匹配,仅关注角色和层级结构。

<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

部分匹配让您可以创建灵活的快照测试,验证页面基本结构而无需强制特定内容或属性。

使用正则表达式进行匹配

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

<h1>Issues 12</h1>

使用正则表达式的aria快照

- heading /Issues \d+/

生成快照

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

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

如果您正在使用Playwright的Code Generator,生成aria快照通过其交互式界面得以简化:

  • "断言快照"操作: 在代码生成器中,您可以使用"断言快照"操作自动为选定的元素创建快照断言。这是将aria快照作为录制测试流程一部分的快捷方式。
  • "Aria快照"标签页: 代码生成器界面中的"Aria快照"标签页直观地展示了所选定位器的aria快照,让您可以探索、检查和验证元素角色、属性和可访问名称,以辅助快照的创建和审查。

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

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

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

npx playwright test --update-snapshots

当应用程序结构变更需要新的快照作为基准时,更新快照非常有用。请注意,Playwright会等待测试运行器配置中指定的最大预期超时时间,以确保在拍摄快照前页面已稳定。如果在生成快照时测试触发了超时,可能需要调整--timeout参数。

用于生成快照的空模板

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

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

请注意,Playwright将等待测试运行器配置中指定的最大预期超时时间,以确保在拍摄快照前页面已稳定。如果在生成快照时测试遇到超时,可能需要调整--timeout参数。

快照补丁文件

在更新快照时,Playwright会创建记录差异的补丁文件。这些补丁文件可以被审查、应用并提交到源代码控制中,使团队能够跟踪结构随时间的变化,并确保更新与应用程序需求保持一致。

源代码的更新方式可以通过--update-source-method标志进行更改。有以下几种选项可供选择:

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

快照作为单独文件

要将快照存储在单独的文件中,请使用带有name选项的toMatchAriaSnapshot方法,并指定.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]