GitLab CI 中的 Visual Testing:将视觉测试集成到你的 Pipelines
视觉测试(visual testing)是一种自动化验证方法,通过比较 Web 界面在两个版本之间的截图来检测图形回归——一个移位的元素、一个改变的颜色、一个溢出容器的组件。
在 Delta-QA,我们每天都在使用 GitLab。我们的仓库、我们的 pipelines、我们的 merge requests、我们的 CI/CD——一切都运行在 GitLab 上。这不是一个默认选择:这是我们为一个原生集成 pipeline、容器注册表以及端到端一致 DevOps 理念的平台做出的深思熟虑的选择。
当我们谈论 GitLab CI 中的视觉测试时,我们并不是在照搬昨天读到的文档。我们分享的是实际使用中学到的经验。本文涵盖了可用的方法、影响视觉测试的 GitLab CI 特性,以及如何实现可靠的视觉回归 pipeline。
为什么 GitLab CI 非常适合视觉测试
GitLab CI 具有使其特别适合视觉测试的特性——这些特性是 GitHub Actions 或 Jenkins 用户默认不具备的。
原生 Artifacts
GitLab CI 原生管理 pipeline artifacts。当视觉测试生成 HTML 报告、diff 图片或截图时,你将它们声明为 artifacts,即可直接从 merge request 界面访问。无需外部服务来存储和查看结果。
这是一个被低估的优势。使用 GitHub Actions 时,你需要配置单独的 artifact 上传或使用第三方服务来使结果可访问。在 GitLab 中,这是原生的。
Review 环境
GitLab 提供 Review Apps:为每个 merge request 自动部署的临时环境。你的应用运行在专用环境中,通过临时 URL 访问。这是视觉测试的理想环境:稳定、隔离,且能代表生产环境。
自托管 Runners
GitLab 允许你使用托管在自己基础设施上的 runners。对于视觉测试来说,这至关重要:你可以控制渲染环境(操作系统、字体、GPU),从而减少由环境差异导致的误报。我们使用固定配置的专用 runners 来保证截图的可复现性。
内置容器注册表
每个 GitLab 项目都有一个容器注册表。你可以存储一个为视觉测试预配置的 Docker 镜像——包含正确的字体、正确的浏览器、正确的依赖——并将其作为测试 jobs 的基础。这消除了一个主要的不稳定性来源。
GitLab CI 中视觉测试的方法
Playwright 在 GitLab CI Job 中
Playwright 是 CI 中进行视觉测试最强大的开源工具。其原生方法 toHaveScreenshot() 管理截图捕获、比较和自动重试。
**与 GitLab CI 的集成。**你在 .gitlab-ci.yml 中创建一个 job,使用 Playwright 的官方 Docker 镜像,运行测试,并将结果作为 artifacts 发布。Playwright 的 HTML 报告可以直接在 GitLab 中查看。
关于 YAML 文件的确切结构,可以问问你的 AI 助手——它在 GitLab CI 语法方面还不错,这大概是它唯一不会产生幻觉的事情(目前为止)。说正经的,Playwright 针对 CI 环境的官方文档是你最好的参考。
**效果好的方面。**Playwright 的官方 Docker 镜像包含所有浏览器和所需的系统依赖。结合 GitLab 容器注册表,你可以创建一个包含你的字体和特定配置的派生镜像。GitLab artifacts 使测试报告无需额外配置即可访问。
**GitLab 环境中的局限。**Baselines 必须在 CI 环境中生成,而不是在本地。这是视觉测试的通用规则,但 GitLab 简化了操作:你可以手动触发 pipeline 来重新生成 baselines。在 Git 中管理 baselines 仍然是一个挑战(二进制文件、merge 冲突),但 GitLab LFS 是原生集成的。
Percy 与 GitLab CI
Percy(BrowserStack)提供与 GitLab CI 的官方集成。Percy SDK 在你的 pipeline 期间捕获快照,并将它们发送到 Percy 云端进行比较和审查。
**效果好的方面。**Percy 自动检测 GitLab 的分支和 merge request。结果作为外部状态显示在你的 MR 上。跨浏览器测试在云端管理。
**局限。**按快照计费仍然是一个问题。而且你为 pipeline 增加了一个外部依赖——如果 Percy 不可用,你的检查将处于等待状态。对于专门选择 GitLab 来控制自己基础设施的团队来说,这种外部依赖可能与初衷相矛盾。
BackstopJS 在 GitLab CI 中
BackstopJS 通过其官方 Docker 镜像在 GitLab CI 中运行。HTML 报告非常适合 GitLab 的 artifact 系统。
**效果好的方面。**BackstopJS 的 HTML 报告是生态系统中最直观、最易读的之一。作为 GitLab artifact 发布后,可以直接在 MR 界面的浏览器中查看。JSON 场景配置明确且可版本控制。
**局限。**该项目经历过维护不稳定的时期——在投入使用前请检查最近的活动。对于复杂应用,配置可能变得冗长,而且你需要手动管理页面或组件的迭代。
Delta-QA:与 GitLab CI 的原生集成
我们在每天使用 GitLab CI 的过程中构建了 Delta-QA。集成不是事后补充——它是一等公民的使用场景。
**如何运作。**Delta-QA 作为专用 job 集成到你的 GitLab CI pipeline 中。它捕获你的页面,与参考基准进行比较,并报告结果。检测到的差异在专用审查界面中可见,并从你的 merge request 直接链接。
**有何不同。**无需编写或维护测试脚本。无需在仓库中存储 baselines。不会因你的机器与 CI runner 之间的环境差异而产生误报。工具在内部管理渲染稳定性。
**GitLab 优势。**Delta-QA 利用了 GitLab CI 的特性:Review Apps 作为捕获目标,artifacts 用于详细报告,GitLab webhooks 在 pipeline 的恰当时机触发测试。
视觉测试需要了解的 GitLab CI 特性
缓存 vs Artifacts
这是很多人混淆的区别。GitLab CI 的缓存在同一项目的 pipelines 之间共享——用于加速 jobs(npm 依赖、Playwright 浏览器)。Artifacts 是特定 job 的输出——测试报告、截图、diffs。
对于视觉测试,使用缓存来存储浏览器和依赖,使用 artifacts 来存储测试结果。永远不要缓存 baselines——它们必须存在于仓库中,与代码一起进行版本控制。
Stages 和 Jobs 之间的依赖
GitLab CI 将 jobs 组织成顺序执行的 stages。视觉测试必须在你的 Review App 部署之后的 stage 中执行。一个常见的模式:
- build — 应用编译
- deploy-review — Review App 部署
- test-visual — 在 Review App 上进行视觉测试
- cleanup — 环境清理
GitLab CI 的 needs 指令允许你在 jobs 之间创建显式依赖,而无需通过顺序 stages,这可以加速你的 pipeline。
受保护的环境变量
云服务(Percy、Chromatic)的 API 令牌必须作为 CI/CD 变量存储在 GitLab 中。注意:受保护的变量仅在受保护的分支上可用。如果你的 feature 分支未受保护,使用云服务的视觉测试将静默失败——这是一个经典陷阱。
时间和内存限制
视觉测试是资源密集型的。在 headless 浏览器中渲染页面会消耗内存,图像比较需要时间。GitLab.com 的共享 runners 有时间限制(通常每个 job 一小时)和内存限制。对于大规模的视觉测试套件,建议使用具有专用资源的自托管 runners。
构建稳健的视觉测试 Pipeline
以下是我们基于自身经验推荐的方法。
从小处开始,目标明确
不要在第一天就对所有页面进行视觉测试。确定五到十个最关键的页面——用户最先看到的页面,视觉回归对业务影响最大的页面。然后逐步扩展。
使用 Review Apps 作为目标
与其在 CI job 中启动本地服务器,不如部署一个 Review App 并对其进行测试。优势:环境稳定、可访问且具有代表性。劣势:你在 pipeline 中增加了部署时间。这个折中是值得的。
稳定你的渲染环境
创建一个专用于视觉测试的 Docker 镜像,存储在你的 GitLab 注册表中。包含你的应用使用的字体、浏览器的精确版本以及所有系统依赖。对这个镜像进行版本管理。当你的渲染环境被固定后,误报会大幅减少。
以非阻塞模式开始
在最初几周将你的视觉测试 job 配置为 allow_failure: true。这让你的团队在不让视觉测试阻塞 merge requests 的情况下熟悉结果。一旦建立了信心并控制了误报,就切换到阻塞模式。
智能通知
GitLab CI 可以通过不同渠道发送通知(Slack、邮件、webhook)。配置视觉测试通知仅在失败时提醒——不要在成功时通知。目标是在需要时引起注意,而不是用消息淹没你的团队。
常见问题
GitLab CI 在视觉测试方面和 GitHub Actions 一样好吗?
具体到视觉测试,GitLab CI 有原生优势:内置 artifacts、Review Apps、容器注册表和自托管 runners。这些功能使搭建稳定且可复现的视觉测试环境更加容易。GitHub Actions 有自己丰富的市场,但其中一些功能需要额外配置。
在 GitLab CI 中进行视觉测试需要自托管 runners 吗?
不是必须的,但强烈推荐。GitLab.com 的共享 runners 可以工作,但其不固定的硬件配置可能引入渲染差异。具有固定配置(字体、浏览器、分辨率)的自托管 runner 消除了这一误报来源,通常还能提供更好的性能。
如何在 GitLab 仓库中管理视觉测试 baselines?
如果你使用 Playwright 或 BackstopJS,baselines(PNG 文件)存储在你的仓库中。启用 GitLab LFS 以防止二进制文件膨胀你的 Git 历史。对于 baselines 的 merge 冲突,最简单的策略是接受源分支的新 baselines,必要时重新生成。使用 Delta-QA,baselines 由工具管理,不会污染你的仓库。
可以使用 GitLab Review Apps 作为视觉测试环境吗?
可以,这正是我们推荐的方法。Review App 为每个 merge request 提供稳定且隔离的环境。你的视觉测试 job 等待 Review App 部署完成,在临时 URL 上截图,并与参考基准进行比较。这比在 CI job 中临时启动的服务器更可靠。
GitLab CI 中的视觉测试能与 monorepos 配合使用吗?
可以。GitLab CI 支持条件规则,允许你仅在前端文件被修改时触发视觉测试。结合 only:changes 指令,你可以在只有后端变更时避免运行不必要的视觉测试。这对于在 monorepo 中保持快速 pipeline 至关重要。
在 GitLab CI 中进行视觉测试的最佳 Docker 镜像是什么?
Playwright 的官方镜像(mcr.microsoft.com/playwright)是一个很好的起点。它包含浏览器和系统依赖。如果需要更稳定的环境,创建一个派生镜像,添加你的应用字体并固定精确版本。将其存储在你的 GitLab 项目容器注册表中以便快速访问。
结论
GitLab CI 是一个天然适合视觉测试的平台。其原生功能——artifacts、Review Apps、容器注册表、自托管 runners——解决了其他 CI 平台需要手动处理的问题。
但平台不能做所有事情。CI 中的视觉测试仍然是一个工程挑战:稳定渲染、管理 baselines、处理误报,以及构建适用于整个团队的审查工作流。
如果你在使用 GitLab,并且希望在不增加测试脚本复杂性和手动管理 baselines 的情况下将视觉测试添加到你的 pipeline 中,Delta-QA 专为原生集成到你的 GitLab CI 工作流而设计。