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 依赖管理的层级结构

我们来看看一个典型的测试依赖配置长什么样。下面这张图帮你快速理解各模块的关系:

Compose 快照测试依赖关系图 项目 build.gradle.kts Android 应用模块 app/build.gradle.kts Compose BOM 统一管理 compose-bom 版本声明 测试依赖模块 自定义测试库 / 测试fixture Compose UI 测试 compose-ui-test 快照测试核心 roborazzi / paparazzi JUnit 引擎 测试运行基础设施 自定义规则 testRule / testOptions 说明:每一个箭头代表“依赖声明”关系,BOM 负责统一版本,避免冲突 (实际项目中建议再细分 debug/release 变体)

从上图你可以看到,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 关于测试配置的避坑指南

我曾经踩过的坑,你一次都不要踩:

  1. testOptions 必须启用 Android 资源——unitTests.isIncludeAndroidResources = true 不能少,否则 Compose 没法加载主题和资源,快照直接一片黑。
  2. 不要用 debugImplementation——快照测试依赖是通过 testImplementation 或 androidTestImplementation 引入的。debugImplementation 会导致单元测试找不到类。
  3. Robolectric 的版本要匹配 AGP——例如 AGP 8.2.x 搭配 Robolectric 4.12,否则 SdkVersion 报错。
  4. 快照测试输出目录建议单独设置——防止被 gitignore 忽略。我习惯放在 build/reports/snapshots/ 下,CI 里直接归档。

一句话总结配置流程:

  • 先选好 Gradle + AGP + Kotlin 的稳定组合
  • 引入 Compose BOM 统一版本
  • 用 testImplementation 添加 Roborazzi + ui-test-junit4
  • 配置 testOptions 开启 Android 资源
  • 最后在 CI 里运行一次,确认快照生成路径正确

说实话,环境搭建是快照测试最无聊但最重要的一步。我以前总觉得「配个依赖能有多难」,结果被版本冲突、找不到类、资源加载失败轮番教育之后……嗯,现在再做新项目,第一件事就是搭好测试骨架。配置搞定之后,下一件事就是写你的第一个快照测试用例了。