屏幕截图测试

屏幕截图测试是验证应用 UI 的一种非常有效的方法。屏幕截图测试可以存在于组件、功能和应用测试中。

您可以使用第三方工具创建插桩和本地屏幕截图测试。如果您使用 Compose,可以使用官方的 Compose Preview 屏幕截图测试工具

定义

屏幕截图测试会截取 UI 的屏幕截图,并将其与之前批准的图像(称为“参考”或“黄金图像”)进行比较。

A screenshot test compares two images, one new screenshot and one reference image.
图 1. 屏幕截图测试比较两张图像

如果图像相同,则测试通过。如果它们之间存在差异,工具会创建一份报告。

A screenshot test report, showing the reference and new screenshot on either side, and the difference in the middle.
图 2. 屏幕截图测试报告,左右两侧显示参考图和新截图,中间显示差异。

有了这份报告,您有两种可能的响应:

  • 发现新代码中存在错误并修复它。
  • 批准新截图,并用新截图替换参考图像。

屏幕截图测试与常规测试的工作流程不同,因为测试失败并不总是意味着存在错误。

优势

屏幕截图测试的优势在于:

  • 一个屏幕截图测试执行多次断言。例如,单个测试可以检查颜色、边距、大小和字体。
  • 屏幕截图测试比同等行为测试更容易编写、理解和维护。
  • 它们在验证和捕获不同屏幕尺寸上的回归时特别有用。

缺点

然而,屏幕截图测试也可能存在缺点:

  • 处理参考图像可能很麻烦,因为一个大型项目最终可能会有数千张 PNG 图片。
  • 不同的平台(Linux、Mac 和 Windows)会产生略微不同的屏幕截图。
  • 它们比同等行为测试慢。
  • 大量的屏幕截图测试可能会导致问题,例如当一个小的改动影响数千张屏幕截图时。

以下部分提供了解决这些问题的建议。

将屏幕截图测试保持在最低限度

您应该最小化屏幕截图测试的数量,同时最大化回归的反馈和覆盖率。

不同 UI 状态的组合可以非常迅速地增加测试数量。以下是您可以验证应用 UI 某一部分的几种方式:

  • 在不同的主题下
  • 使用不同的字体大小
  • 在不同的屏幕尺寸或边界内

如果您为应用的每个组件、布局和屏幕都这样做,最终您会得到数千个屏幕截图文件,其中大部分都没有提供任何额外的反馈。

例如,如果您想测试一个具有明暗主题和 3 种字体大小的自定义按钮,您无需创建所有这些组合。相反,您可以只选择其中一个主题。这是因为按钮对长单词的反应方式对主题没有影响。

You can omit Some combinations of UI properties.
图 3. 您可以省略 UI 属性的一些组合。

存储参考图像

参考(或黄金)图像通常是 PNG 文件,可以检入到您的源代码控制中。然而,Git 和大多数源代码控制管理器都针对文本文件进行了优化,而不是大型二进制文件。

您有 3 种选项来管理这些文件:

  • 继续使用 Git,但尽量减少存储使用。
  • 使用 Git LFS
  • 使用云服务来管理屏幕截图。

平台差异

屏幕截图测试依赖于底层平台 API 来绘制特定功能,如文本或阴影,而平台可以以不同的方式实现这些功能。如果您在 Mac 上开发并保存本地拍摄的新屏幕截图,您可能会在 Linux CI 机器上看到测试失败。

有两种方法可以解决此问题:

  • 容忍小的更改
  • 在服务器上截取屏幕截图

容忍小的更改

您可以配置大多数屏幕截图测试库,以允许在比较两个屏幕截图时存在微小差异。

这有两种方法:

  • 根据修改像素的百分比或像素值总差异的百分比配置容差。
  • 使用智能差异算法(比较屏幕截图的算法)来验证结构和语义相似性,而不是像素。

这种方法的缺点是它可能产生误报,并且无法捕获低于阈值或被错误地认为是足够相似的错误。

在服务器上截取屏幕截图

要使用像素完美屏幕截图比较器,您必须确保您的测试在相同条件下截取屏幕截图。为此,您可以使用您的持续集成 (CI) 系统或采用云服务。

例如,您可以在 CI 工作流程中创建一个步骤,执行以下操作:

  1. 运行屏幕截图测试(仅在使用非像素完美匹配时需要)。
  2. 如果上一步失败,则记录新屏幕截图。
  3. 将新文件提交到分支。
Alt Text: Diagram showing how to take screenshots on CI
图 4. 显示如何在 CI 上截取屏幕截图的图表

使用这种方法,屏幕截图测试在 CI 上永远不会失败,但它会为您修改更改。这样,您和更改审核者可以通过合并更改来接受新的屏幕截图。

屏幕截图测试工具

考虑屏幕截图测试可用工具和库之间的以下关键差异:

  • 环境:在主机上运行的本地测试,或在模拟器或设备上运行的插桩测试。
  • 渲染引擎:主机端屏幕截图解决方案可以使用 Layoutlib(Android Studio 的预览渲染引擎)或 Robolectric Native Graphics (RNG)。
    • 基于 Layoutlib 的框架专注于渲染静态组件,使用不同的状态来显示不同的行为。它们通常更容易使用。
    • 与 RNG 集成的框架可以使用 Robolectric 的所有功能,从而允许进行更大范围的测试。