第一章 快照测试概述

什么是快照测试?

快照测试,说白了就是把 UI 的渲染结果拍张"照片"存起来。下次跑测试时,再拍一张新的,然后逐像素对比——不一样就报错。

在 Jetpack Compose 里怎么做?我们用 Roborazzi 或 Paparazzi 这类库,让 Composable 在纯 Java 环境下渲染成一张 PNG。这张 PNG 就是基线(baseline)。以后每次改代码,测试工具都会自动截一张新图,跟基线比对。不一样?说明界面变了——可能是你想要的,也可能是个 bug。

核心逻辑: 截图 → 保存基线 → 对比差异 → 判定通过/失败。

我刚开始接触快照测试时觉得这玩意儿太粗暴了。像素级对比?能靠谱吗?后来有个活生生的事让我改变了看法——那次一个 1dp 的阴影偏移,传统测试全绿通过,线上用户却说按钮"长歪了"。嗯,从那以后我就老老实实把快照测试加进了每个组件库。

为什么需要快照测试?

你想想看,传统的 UI 测试怎么做的?

  • 语义匹配:assert(isDisplayed) 检查控件存在,但看不到颜色、圆角、阴影。
  • 属性断言:检查 width、height、padding,但你不会把每个像素的 RGB 值都写出来吧?
  • 截屏对比(手动):每次发版前人工打开 App 扫一遍?那基本是走马观花。

快照测试直接把"视觉结果"变成可断言的值。你改了一个主题色?基线图片自动告诉你有多少地方被影响了。我个人习惯在 CI 流水线里加一步快照对比,哪怕只是改了某个 Composable 的 Modifier.padding,也能立刻看到 Layout 是否跑偏。

类型能发现什么发现不了的
单元测试逻辑错误像素级视觉偏差
语义测试元素存在/缺失颜色、阴影、间距
快照测试任意视觉差异交互行为、动画时序

我遇到过最经典的案例:某次升级 Compose BOM 版本后,所有 Button 的圆角从 12dp 变成了 16dp。单元测试全部通过,人工 review 也没注意。快照测试直接标红了 47 张图——每个带按钮的页面都变了。你说值不值?

典型应用场景

不是什么项目都适合上快照测试。根据我的经验,下面几类场景效果最好:

  1. 组件库 / Design System
    你有一个统一的 PrimaryButton、SecondaryButton……改一个基础样式会影响所有用法。快照测试能保证"牵一发而全身皆知"。
  2. 主题切换验证
    Light / Dark 模式、高对比度主题、品牌色更换。跑一遍快照,所有主题下的所有组件截出来,对比基线——完美覆盖。
  3. 多屏幕 / 多语言适配
    不同屏幕密度、不同 Locale 下文字长度不一样。快照测试能帮你发现文本溢出、布局断裂。
  4. 自定义绘制 (Canvas)
    Compose 里用 Canvas 或 drawBehind 的图形,常规测试根本没法断言。快照是唯一靠谱的方式。
  5. 动画关键帧
    虽然快照不能测试完整的 60fps 动画,但你可以截取动画的起止状态或中间关键帧,确保过渡正确。

局限性

话不能说太满。快照测试不是银弹,我自己踩过不少坑:

我曾经遇到过一个坑:

  • 在 Mac 上生成的基线图片是 Retina 分辨率(@2x),但 CI 机器是 Linux,字体渲染差异导致 90% 的测试失败。费了半天才搞清楚,后来强制统一用 robolectric 的虚拟屏幕密度。

这里列举几个主要局限:

  • 平台渲染差异: macOS、Windows、Linux 的字体渲染引擎不一样。同一段文本在不同 OS 上截出来的像素可能差 1~2px。解决方案:统一在 Docker 容器或同一套 JDK + 字体环境下运行快照测试。
  • 像素级敏感: 1px 的样式变化就会导致测试失败。有时候是设计师故意微调,有时候只是反走样算法波动。你需要一个合理的 阈值容忍度(比如 tolerance = 0.1%)。
  • 维护成本: 故意改 UI 后必须手动更新基线图片,推一个新的 PR。如果一个团队频繁改视觉样式,基线图片会变成"变更清单",测试反而变成负担。
  • 没法测交互: 快照是静态的,不能验证点击、滑动、长按后的状态变化(除非你手动触发并重新截图)。
  • 基线膨胀: 成百上千张 PNG 塞进 Git 仓库,历史记录会变得很重。我建议用 Git LFS 或专门的对象存储来管理。

我的建议: 快照测试只用在"相对稳定"的组件上——那些设计稿定稿后很少改的部分。对于快速迭代的页面,可以只对关键区域做快照,或者推迟到功能冻结后再加入。

总结一下:快照测试是 UI 回归的最后一道防线,但不是全部防线。它跟单元测试、集成测试、人工走查互补。理解它的能力和边界,才能用好它。

快照测试知识体系 快照测试 定义 截图 → 基线 → 像素对比 为什么需要 发现视觉回归 典型场景 组件库 / 主题 / 多屏幕 局限性 平台差异 / 维护成本 工作流程 截图 对比 报告差异 核心要点 快照测试 ≠ 单元测试;它只测视觉,不测逻辑。 为什么 & 局限性 核心定义 & 场景 工作流程