截图测试 (Screenshot Testing)
UI 测试通常验证“按钮是否可点”,而截图测试验证“像素是否偏移”。对于防止 UI 回归(Regression)至关重要。
1. 为什么需要截图测试?
- 无需真机: 它们通常在 JVM 上运行,速度极快(几秒钟生成数百张图)。
- 像素级精确: 哪怕是 1px 的 padding 变化都能被检测出来。
- 版本控制: 截图作为 Git 的一部分,Code Review 时可以直接看到 UI 变化。
2. 工具选择
目前主流的两个库:
| 特性 | Paparazzi (Cash App) | Roborazzi (Takahirom) |
|---|---|---|
| 原理 | 使用 Android Studio 的 LayoutLib (Preview 引擎) | 使用 Robolectric (无头 Android 模拟器) |
| 速度 | 极快 | 较快 |
| 准确度 | 接近 Preview,可能有细微差异 | 接近真实设备行为 |
| 交互支持 | 不支持 (静态渲染) | 支持点击、滚动后再截图 |
3. 使用 Paparazzi
配置
kotlin
// build.gradle
plugins {
id("app.cash.paparazzi") version "1.3.1"
}编写测试
kotlin
class ButtonSnapshotTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = DeviceConfig.PIXEL_5,
theme = "android:Theme.Material.Light.NoActionBar"
)
@Test
fun snapButton() {
paparazzi.snapshot {
MyTheme {
Button(onClick = {}) { Text("Snapshot Me") }
}
}
}
}运行
./gradlew recordPaparazzi: 生成基准截图(Golden Images)。./gradlew verifyPaparazzi: 运行测试并对比当前截图与基准截图。
如果对比失败,它会生成一个带有差异高亮的 HTML 报告。
4. 最佳实践
- 为组件库编写截图测试: 确保原子组件(Button, Card, Input)的稳定性。
- 测试不同配置: 利用 Parameterized Test 自动测试 Light/Dark 模式、不同字体缩放、RTL 布局。
- 不要测试整个屏幕: 屏幕太复杂且易变,容易导致测试频繁失败(Flaky)。专注于组件级测试。