Show / Hide Table of Contents ]

视觉回归测试

Last updated: 2024-10-25 09:27:04

什么是视觉回归测试?

在此之前,需要知道另一个概念“回归测试”,它指的是验证我们对源代码的修改不会对系统产生意外的影响。
那么对于视觉回归测试,它的目标是相同的,但它更关心呈现给最终用户的界面,而不是系统的功能如何。视觉回归测试的目 的是发现视觉上的 “缺陷”,是功能测试工具无法发现的,如错位的按钮、重叠的图像或文本、部 分可见的元素和渲染问题等等。
从本质上讲,视觉回归测试使我们能够通过当前截图和之前图片快照之间进行比较,了解用户将感知到的变化。
在下面的图中(如图 1 所示),人眼就能发现第二例中的网页有视觉缺陷(标题和信息文本重叠,使内容难以辨认)。这些缺陷在功能测试(e2e)中不会被注意到,因为功能测试(e2e)能够找到所有的元素并点击按钮,不管它被放在哪里。像这样的情况会导致用户有非常不愉快的体验,甚至影响可用性。


图 1. 视觉缺陷示例

为什么需要做视觉回归测试?

我们已经在代码库中写了很多测试,用来覆盖很多业务情况,并给我们的代码库的质量带来一些信心。那么,在项目中引入另一种类型的测试(视觉回归测试)背后的动机是什么呢?

动机一:发现视觉缺陷

由于我们的业务模块是依赖于组件进行开发,一旦组件内部实现发生变化很容易导致业务模块发生不可预期的视觉缺陷;此外,随着第三方库变更或者组件版本的升级会废弃 API 或者变更 API 使用,如果业务模块未同步更新其内容也容易引发不可预期的视觉缺陷;或者其他种种因素导致的视觉缺陷。

动机二:功能与设计相符

正如我们所知,一般的功能测试(单元测试等)对于保证业务模块按预期的功能工作是必不可少的。然而,它们并不能保证呈现给用户的界面是可靠的。
因为这些测试不能捕捉到关于用户体验的问题。并且这些问题对于我们的用户来说也是令人讨厌和阻碍的问题。
以下图为例,这里有一个「弹窗框」的截图。它可以很容易地通过功能测试,因为就功能而言,它是可以正常工作的;所有我们想要的东西都被渲染了,与按钮绑定的预期动作也正常工作了。


图 2. 功能测试的缺陷

然而,当我们关注视觉效果时,这里的最终结果是不理想的(未符合设计预期)。导致不理想的原因,可能是在对全局组件进行 CSS 修改时引入的,这个修改或许只适用于业务模块本地样式,也可能是一些库的版本更新导致的。
对于这个例子,通过视觉回归测试就可以更容易地在用户之前捕捉到这些变化(是否符合预期的变化),从而使得在用户之前可以让设计与功能相符

动机三:视觉变化记录

通过视觉回归测试,我们也可以很容易地在代码仓库获得一个可视化的变更日志。通过查看快照的历史,可以跟踪界面的每一个视觉变化情况;

解决方案

虽然我们最终使用开源的库实现了一个定制化的方案,但也可以简单地了解一下还有哪些其它方案可选。

付费工具

Percy

Percy是视觉回归测试最著名的工具之一,它非常灵活,易于使用。快照变更可由团队审查批准/拒绝。适用于业务界面的视觉回归测试。

Chromatic

Chromatic 是由 Storybook 的维护者为Storybook 创建的。它是与Storybook集成的开箱即用的,与 Percy 相比,它有一个非常好的协作式仪表板,在很多方面都非常相似。但适用于组件的视觉回归测试;

开源工具

BackstopJS

BackstopJS 是一个非常受欢迎的视觉回归开源项目,维护良好,非常完整和灵活。它生成了一份漂亮的 HTML 可视化报告,其中包含了所发现的差异。与 percy 类似;

Loki

Loki 是一个非常容易使用的工具,适用于使用 Storybook 的项目。与 chromatic类似,适合组件视觉回归测试;但无可视化报告。

视觉测试的自动化过程

步骤:


图 3. 测试过程

  1. 编写测试场景:定义将在屏幕截图中捕获的内容以及从系统中捕获它们的位置。此外,这些场景应该处理任何必要的用户交互。
  2. 在系统中运行测试工具,以便根据先前编写的场景捕获所有屏幕截图。
  3. 通过工具运行一种 diff 算法:将最近捕获的屏幕截图与截图快照进行比较(下图);参考截图。然后生成一份报告,其中包含在比较中发现的所有差异。
  4. 业务负责人分析报告并确定引入的差异(如果有)是否符合预期(符合设计预期)。如果不符合预期,修复差异,将返回到第 2 步
  5. 引入的差异符合预期时,必须更新参考快照以供将来运行测试。


图 4. 测试报告

视觉回归测试实践

要使上述内容发挥作用,需要很多不同的部分。下面,将介绍一些需要的工具和策略,以及在建立一个定制化的视觉测试解决方案时可能遇到的一些问题。最后,会考虑一些潜在的下一步行动。

Docker

我们的代码库中添加视觉回归测试时,会遇到的第一件事就是测试运行的环境。因为在所有的操作系统中,字体和颜色的呈现方式是不一样的。这种差异足以让像素差异算法认为在每个操作系统中生成的图像是不兼容的,即使它们渲染的是相同的底层源代码。其结果是:如果有人在 Mac 上运行测试用例并生成的快照,但是在Windows 或 Linux 上运行视觉回归测试时,所有的测试可能都会失败(下图)


图 5. 不同操作系统的差异

那么要解决上图中的字体渲染不一样的问题,可行的方案是始终在相同的环境中运行测试,这也就意味着我们会采用在 Docker 容器中运行测试方式,使得每次进行视觉回归测试时的环境是相同的;

Cypress

借助 Cypress,可以轻松地为我们的项目创建视觉回归测试用例。例如可以利用它模拟用户操作进入对应的业务界面

截图尺寸

图片的大小也是我们需要重点考虑的事情之一,在项目中常见使用的页面设计是 1440 * 900 ,所以一般会根据设计图的尺寸进行设置为截图的尺寸为 1440 * 900;也就是对浏览器设置为window size: 1440 * 900 ,然后对页面进行全页面进行截图;

确定性

对于视觉回归测试来说,每次测试的结果它应该是确定性的。如果在具有相同输入的相同环境中运行,它们应该产生相同的结果。然而,即使在确定了一致的环境之后,UI 界面中也可能存在导致每次测试结果的不同因素。显然,当测试运行时,我们不希望这类因素成为测试未通过的原因。
以下列举了在快照中产生不稳定的几个主要因素:

  • 动画
    • 如果有任何使用动画的组件,将要cypress 蒙版功能忽略它或者关闭它们。避免其影响视觉回归测试;
  • 异步数据
    • 在测试需要交互的组件时,经常需要等待异步数据,然后才能继续进行交互的下一步。
      • 有时候为了简单方便会使用 wait 预估的时间方式。这是不推荐的方式,因为随着时间的推移,这些等待时间会累积起来,会使测试运行速度慢得令人难以忍受。
      • 更好的方法是等待异步数据上加断言,并等待断言通过。
  • 动态随机数据
    • 在 mocking 环境中,很有可能会出现随机数字或者随机布尔类型对应的界面显示;
      • 对于随机的数字或布尔值,需要保证在 mocking 中是一个固定不变的或者使用 cypress 蒙版功能忽略它们;

开发人员用户体验

在此,我们可能需要思考🤔️几个问题?

  1. 消息同步对于我们来说是十分重要的。如果某个时间测试出现了问题,但是没有及时的消息同步,或许要很长一段时间才能发现该问题;这其实对于我们开发人员来说是不友好的,因为我们不能及时响应错误,会导致问题持续下去;
    1. 因此我们会引入 「飞书机器人🤖️」通知,将测试的错误信息第一时间反馈到工作群;从而我们可以做到快速响应错误,并进行响应错误的动作处理;
  2. 当视觉回归测试失败时,我们该怎么定位问题呢?
    1. 首先,我们第一直觉最想做的必然是能够访问 CI 环境,因为这样可以阅读测试运行的输出;但很多情况下,即使知道哪些测试失败也不是特别有用,因为它并不能给我们带来更加直观的信息用于判断具体是哪里的问题。
    2. 因此,我们需要可视化的测试报告,帮助我们去定位视觉缺陷的具体原因;
  3. 我们项目中已经拥有了 e2e 测试路径,如果加入视觉回归测试是否会带来一些编写页面操作场景的重复工作呢?
    1. 不会,视觉回归测试它可以加入到任何一个 e2e 测试路径中,这样可以减少我们编写测试用例的成本;
    2. 当然,我们也可以单独编写视觉回归测试用例,这样可以减少 e2e 的逻辑复杂性;
    1. 对于这部分,我们可以充分的利用 Cypress Studio 的自动化功能,快速帮我们自动编写测试用例;

未来研究

Figma

视觉回归测试虽然很大程度上已经帮助我们回归视觉缺陷问题。但如果能够将 figma 设计稿与开发者界面最终实现进行视觉回归的话,它就能达成「design - code - test」自动闭环的理想预期;
那么我们要做到这一点,可能会有很长一段路要走;比如:

  • 研究 Figma 设计稿以何种形式与我们的界面实现进行比较?
  • 研究 Figma 设计稿如何保证与开发者的 mocking 环境对齐?
  • 研究 Figma 的设计稿字体如何保证与 docker linux 环境一致?

速度问题

视觉回归测试是 CLI 中运行时间比较长的任务,每个用例为测试运行至少增加了大约20 ~ 30 秒。虽然这可能与 e2e 任务一起运行的,但如果能将这一时间减半或四分之一,那就更理想了。要做到这一点,我们需要研究视觉回归测试中哪些因素会增加运行时间,从而不断的优化视觉回归测试的执行时间;

Git

视觉回归测试的快照目前给我们的 Git 仓库增加了大约 3.4 MB 存储占用,而存储大量图片可能会导致 Git 仓库变得臃肿?因为占用大量磁盘空间,使仓库复制和克隆操作变得缓慢。此外,每次提交或拉取时,Git 需要比较每个文件的内容,包括大量图片,会大大降低执行速度;
因此随着项目的发展,我们可能需要考虑使用 Git LFS 来管理大文件内容。

感谢阅读📖!

重拾纯粹的写作