屏幕截图测试

屏幕截图测试是一种非常有效的验证应用界面的方法。屏幕截图测试可在组件、功能和应用测试中执行。

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

定义

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

屏幕截图测试会比较两张图片,一张新屏幕截图和一张参考图片。
图 1. 屏幕截图测试会比较两张图片

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

屏幕截图测试报告,两侧显示的是参考屏幕截图和新屏幕截图,中间显示的是差异。
图 2. 屏幕截图测试报告,两侧显示的是参考屏幕截图和新屏幕截图,中间显示的是差异。

收到报告后,您可以采取以下两种处理方式:

  • 发现新代码中存在错误并加以修正。
  • 批准新的屏幕截图,并将参考图片替换为新图片。

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

优点

屏幕截图测试的优势如下:

  • 屏幕截图测试会针对每个测试执行多个断言。例如,单个测试可以检查颜色、边距、尺寸和字体。
  • 与等效的行为测试相比,屏幕截图测试更易于编写、理解和维护。
  • 在验证和捕获不同屏幕尺寸上的回归问题时,这些工具特别有用。

缺点

不过,屏幕截图测试也有一些缺点:

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

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

尽量减少屏幕截图测试

您应尽量减少屏幕截图测试的数量,同时尽可能提高回归问题的反馈和覆盖率。

组合使用不同界面状态会使测试数量迅速增加。您可以通过以下方式验证应用界面的某一部分:

  • 针对不同主题
  • 使用不同字号
  • 在不同的屏幕尺寸或边界内

如果您对应用的每个组件、布局和屏幕执行此操作,最终会得到数千个屏幕截图文件,其中大多数文件都不会为您提供任何额外的反馈。

例如,如果您要测试采用浅色和深色主题且采用 3 种字体大小的自定义按钮,则无需创建所有这些组合。您可以只选择其中一个主题。这是因为按钮对长单词的响应方式对主题没有影响。

您可以省略某些界面属性组合。
图 3. 您可以省略界面属性的某些组合。

存储参考图片

参考(或金标准)图片通常是 PNG 文件,可以签入源代码控制系统。不过,Git 和大多数源代码管理器都是针对文本文件(而非大型二进制文件)进行了优化。

您可以通过 3 种方式管理这些文件:

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

平台差异

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

您可以通过以下 2 种方式解决此问题:

  • 容忍小幅改变
  • 在服务器上截取屏幕截图

容许细微变化

您可以对大多数屏幕截图测试库进行配置,以便在比较两个屏幕截图时允许出现细微差异。

您可以采用下列两种方法:

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

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

在服务器上截取屏幕截图

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

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

  1. 运行屏幕截图测试(仅在未使用像素级匹配时需要)。
  2. 如果上一步失败,请记录新的屏幕截图。
  3. 将新文件提交到分支。
替代文本:显示如何在 CI 上截取屏幕截图的示意图
图 4. 显示如何在 CI 上截取屏幕截图的示意图

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

屏幕截图测试工具

请考虑以下可用于屏幕截图测试的工具和库之间的主要区别:

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