2. Compose 测试环境搭建:Gradle 配置、依赖管理与版本选择
搭建测试环境是快照回归的第一步。这一步没做好,后面所有的工作都是空中楼阁。我刚开始搞 Compose 快照测试的时候,就被版本冲突折磨了一整天。所以今天咱们把这块彻底理清楚。
2.1 Gradle 版本与 AGP 的选择
先说一个核心原则:Gradle 版本、Android Gradle Plugin(AGP)版本、Compose 编译器版本三者必须兼容。我自己查官方兼容性表查得头皮发麻,后来直接总结了几个稳定组合。
我的生产环境推荐组合(2025年稳定):
- Gradle 8.5 + AGP 8.2.2 + Compose BOM 2024.12.01
- 如果你用 Kotlin 2.0+,Compose 编译器要单独指定版本(Kotlin 2.0 以上不再内置 Compose 编译器插件)
为什么要强调这个?原因很简单:快照测试依赖 Compose 的渲染管线,编译器版本错一点,生成的快照就不一样了。我之前遇到过,同样的代码,换个 Compose 编译器版本,快照颜色值差 0.5px,回归测试直接挂了。
2.2 依赖管理的层级结构
我们来看看一个典型的测试依赖配置长什么样。下面这张图帮你快速理解各模块的关系:
从上图你可以看到,BOM(Bill of Materials)是核心。它像一个大管家,帮你统一管理所有 Compose 相关库的版本。我个人强烈建议你使用 Compose BOM,而不是一个个手动指定版本——防止版本分裂的噩梦。
2.3 核心依赖配置实战
好,直接上代码。这是我在项目中经过反复打磨的配置,你拿去就能用。
2.3.1 根项目 build.gradle.kts
// settings.gradle.kts
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
// 项目级 build.gradle.kts
plugins {
id("com.android.application") version "8.2.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}
2.3.2 模块级 build.gradle.kts(核心测试依赖)
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
compileSdk = 34
defaultConfig {
minSdk = 26
targetSdk = 34
}
// 快照测试需要开启 testOptions
testOptions {
unitTests.isIncludeAndroidResources = true
unitTests.isReturnDefaultValues = false
}
}
dependencies {
// ----- Compose BOM 统一版本管理 -----
val composeBom = platform("androidx.compose:compose-bom:2024.12.01")
implementation(composeBom)
androidTestImplementation(composeBom)
// ----- Compose UI(生产依赖)-----
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.0")
// ----- 测试依赖 -----
// Roborazzi(我的首选快照测试库)
testImplementation("io.github.takahirom.roborazzi:roborazzi:1.35.0")
// paparazzi 备选(如果你用 Layout Inspector 方式)
// testImplementation("app.cash.paparazzi:paparazzi:1.3.1")
// Compose UI 测试工具
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("androidx.compose.ui:ui-test-manifest")
// JUnit 5(我习惯用 Jupiter)
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// 用于自定义测试规则的扩展
testImplementation("org.robolectric:robolectric:4.12")
testImplementation("androidx.test:core:1.5.0")
testImplementation("androidx.test:rules:1.5.0")
testImplementation("androidx.test.ext:junit:1.1.5")
}
个人经验提示:
- Roborazzi 和 Paparazzi 不建议同时用,测试输出路径和图像比较机制会打架。我踩过这个坑。
- Compose BOM 的版本号建议 固定为月份版本(如 2024.12.01),不要用 + 通配符。否则下次 CI 自动升级可能悄悄改快照。
2.4 版本选择的魔鬼细节
这里有个很容易翻车的地方——Compose 编译器版本。从 Kotlin 1.9.x 开始,Compose 编译器插件和 Kotlin 版本解耦了。如果你用 Kotlin 2.0+,必须单独声明:
// 在 kotlin 2.0+ 项目中
plugins {
id("org.jetbrains.kotlin.plugin.compose") version "2.0.0"
}
// 或者用 compiler extension 的方式
composeCompiler {
targetKotlinVersion = "2.0.0"
// 也可以指定具体插件版本
// kotlinCompilerExtensionVersion = "1.5.13"
}
为什么这个重要? 快照测试的底层是 ComposeTestRule 去渲染组件。如果 Compose 编译器版本和 UI 库版本不一致,渲染出来的像素可能偏移 1-2px,测试直接亮红灯。我曾在升级 Kotlin 2.0 时忘了更新 Compose 插件,浪费了整整半天查 bug。
| Kotlin 版本 | 推荐 Compose 编译器版本 | 推荐 AGP 版本 | 我的评价 |
|---|---|---|---|
| 1.9.22 | 内置(1.5.12) | 8.2.2 | 最稳定,无坑 |
| 2.0.0 | 1.6.10(独立插件) | 8.4.0+ | 需要额外配置,但性能更好 |
| 2.0.21(最新) | 1.7.0(独立插件) | 8.5.0+ | 我目前用这个,很丝滑 |
2.5 关于测试配置的避坑指南
我曾经踩过的坑,你一次都不要踩:
- testOptions 必须启用 Android 资源——
unitTests.isIncludeAndroidResources = true不能少,否则 Compose 没法加载主题和资源,快照直接一片黑。 - 不要用 debugImplementation——快照测试依赖是通过 testImplementation 或 androidTestImplementation 引入的。debugImplementation 会导致单元测试找不到类。
- Robolectric 的版本要匹配 AGP——例如 AGP 8.2.x 搭配 Robolectric 4.12,否则 SdkVersion 报错。
- 快照测试输出目录建议单独设置——防止被 gitignore 忽略。我习惯放在
build/reports/snapshots/下,CI 里直接归档。
一句话总结配置流程:
- 先选好 Gradle + AGP + Kotlin 的稳定组合
- 引入 Compose BOM 统一版本
- 用 testImplementation 添加 Roborazzi + ui-test-junit4
- 配置 testOptions 开启 Android 资源
- 最后在 CI 里运行一次,确认快照生成路径正确
说实话,环境搭建是快照测试最无聊但最重要的一步。我以前总觉得「配个依赖能有多难」,结果被版本冲突、找不到类、资源加载失败轮番教育之后……嗯,现在再做新项目,第一件事就是搭好测试骨架。配置搞定之后,下一件事就是写你的第一个快照测试用例了。