Compose 预览屏幕截图测试

屏幕截图测试是一种有效的方法,可用于验证界面在用户眼中的外观。Compose 预览版屏幕截图测试工具兼具 composable 预览版的简洁性和功能,以及运行主机端屏幕截图测试带来的效率提升。Compose 预览版屏幕截图测试旨在实现与可组合项预览一样简单易用的体验。

屏幕截图测试是一种自动化测试,用于截取部分界面元素的屏幕截图,然后将其与之前批准的参考图片进行比较。如果图片不匹配,测试会失败并生成 HTML 报告,帮助您比较并找出差异。

借助 Compose 预览版屏幕截图测试工具,您可以:

  • 使用 @PreviewTest 为现有或新的可组合预览创建屏幕截图测试。
  • 根据这些可组合项预览生成参考图片。
  • 生成 HTML 报告,用于在您更改代码后识别这些预览的更改。
  • 使用 @Preview 参数(例如 uiModefontScale)和多重预览来帮助您扩大测试范围。
  • 使用新的 screenshotTest 源集将测试模块化。
图 1. HTML 报告示例。

IDE 集成

虽然您可以手动运行底层 Gradle 任务(updateScreenshotTestvalidateScreenshotTest)来使用 Compose 预览版屏幕截图测试工具,但 Android Studio Otter 3 功能更新 Canary 4 引入了完整的 IDE 集成。这样,您就可以完全在 IDE 中生成参考图片、运行测试和分析验证失败情况。以下是一些主要功能:

  • 编辑器中的边线图标。您现在可以直接从源代码运行测试或更新参考图片。在带有 @PreviewTest 注释的可组合函数和类旁边的边线中,会显示绿色的运行图标。
    • 运行屏幕截图测试。专门针对单个函数或整个类执行测试。
    • 添加或更新参考图片。专门针对所选范围触发更新流程。

  • 互动式参考管理。更新参考图片现在更安全、更精细。
    • 新的参考图片生成对话框。现在,您无需运行批量 Gradle 任务,只需通过新对话框直观地选择要生成或更新哪些预览即可。
    • 预览变体。对话框会单独列出所有预览变体(例如浅色或深色模式,或不同的设备),以便您在生成图片之前选中或取消选中特定项目。

  • 集成的测试结果和差异查看器。无需离开 IDE 即可查看结果。
    • 统一的运行面板。屏幕截图测试结果显示在标准的 Run 工具窗口中。测试按类和函数分组,并清楚标记通过或失败状态。
    • 可视化差异工具。如果测试失败,您可以在屏幕截图标签页中并排比较参考实际差异图片。
    • 详细属性。属性标签页提供有关失败测试的元数据,包括匹配百分比、图片尺寸和所用的具体预览配置(例如 uiModefontScale)。

  • 灵活的测试范围界定。现在,您可以直接从“项目”视图中执行各种范围的屏幕截图测试。右键点击模块、目录、文件或类,即可专门针对所选内容运行屏幕截图测试。

要求

如需通过完整的 IDE 集成使用 Compose 预览版屏幕截图测试,您的项目必须满足以下要求:

  • Android Studio Panda 1 Canary 4 或更高版本。
  • Android Gradle 插件 (AGP) 版本 9.0 或更高版本。
  • Compose 预览版屏幕截图测试插件版本 0.0.1-alpha13 或更高版本。
  • Kotlin 版本 1.9.20 或更高版本。我们建议使用 Kotlin 2.0 或更高版本,以便您可以使用 Compose 编译器 Gradle 插件。
  • JDK 17 版或更高版本。
  • 已为您的项目启用 Compose。我们建议使用 Compose 编译器 Gradle 插件启用 Compose。

如果您只想使用底层 Gradle 任务,而无需 IDE 集成,则需要满足以下要求:

  • Android Studio Panda 1 Canary 4 或更高版本。
  • Android Gradle 插件 (AGP) 版本 8.5.0 或更高版本。
  • Compose 预览版屏幕截图测试插件版本 0.0.1-alpha13 或更高版本。
  • Kotlin 版本 1.9.20 或更高版本。我们建议使用 Kotlin 2.0 或更高版本,以便您可以使用 Compose 编译器 Gradle 插件。
  • JDK 17 版或更高版本。
  • 已为您的项目启用 Compose。我们建议使用 Compose 编译器 Gradle 插件启用 Compose。

设置

集成式工具和底层 Gradle 任务都依赖于 Compose 预览版屏幕截图测试插件。如需设置插件,请按以下步骤操作:

  1. 在项目的 gradle.properties 文件中启用实验性属性。
          android.experimental.enableScreenshotTest=true
        
  2. 在模块级 build.gradle.kts 文件的 android {} 块中,启用实验性标志以使用 screenshotTest 源代码集。
          android {
              experimentalProperties["android.experimental.enableScreenshotTest"] = true
          }
        
  3. com.android.compose.screenshot 插件(版本 0.0.1-alpha13)添加到您的项目中。
    1. 将插件添加到版本目录文件中:
                [versions]
                agp = "9.0.0-rc03"
                kotlin = "2.1.20"
                screenshot = "0.0.1-alpha13"
      
                [plugins]
                screenshot = { id = "com.android.compose.screenshot", version.ref = "screenshot"}
              
    2. 在模块级 build.gradle.kts 文件中,在 plugins {} 代码块中添加插件:
                plugins {
                    alias(libs.plugins.screenshot)
                }
              
  4. 添加 screenshot-validation-apiui-tooling 依赖项。
    1. 将它们添加到您的版本目录中:
                [libraries]
                screenshot-validation-api = { group = "com.android.tools.screenshot", name = "screenshot-validation-api", version.ref = "screenshot"}
                androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling"}
              
    2. 将它们添加到模块级 build.gradle.kts 文件中:
                dependencies {
                  screenshotTestImplementation(libs.screenshot.validation.api)
                  screenshotTestImplementation(libs.androidx.ui.tooling)
                }
              

指定用于屏幕截图测试的可组合项预览

如需指定要用于屏幕截图测试的可组合项预览,请使用 @PreviewTest 注解标记预览。预览必须位于新的 screenshotTest 源集中,例如:

app/src/screenshotTest/kotlin/com/example/yourapp/ExamplePreviewScreenshotTest.kt

您可以在此文件或在同一源代码集中创建的其他文件中添加更多可组合项和/或预览(包括多重预览)。

package com.example.yourapp

import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.android.tools.screenshot.PreviewTest
import com.example.yourapp.ui.theme.MyApplicationTheme

@PreviewTest
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        Greeting("Android!")
    }
}

生成参考图片

设置测试类后,您需要为每个预览生成参考图片。这些参考图片用于在您进行代码更改后识别后续更改。如需为可组合项预览版屏幕截图测试生成参考图片,请按照以下说明操作,选择使用 IDE 集成或 Gradle 任务。

在 IDE 中

点击 @PreviewTest 函数旁边的边线图标,然后选择 Add/Update Reference Images。在对话框中选择所需的预览,然后点击添加

使用 Gradle 任务

运行以下 Gradle 任务:

  • Linux 和 macOS:./gradlew updateDebugScreenshotTest (./gradlew :{module}:update{Variant}ScreenshotTest)
  • Windows:gradlew updateDebugScreenshotTest (gradlew :{module}:update{Variant}ScreenshotTest)

任务完成后,在 app/src/screenshotTestDebug/reference ({module}/src/screenshotTest{Variant}/reference) 中查找参考图片。

生成测试报告

参考图片存在后,请按照以下说明(针对 IDE 集成或 Gradle 任务)生成测试报告。

在 IDE 中

点击 @PreviewTest 函数旁边的边线图标,然后选择 Run '...ScreenshotTests'

如果测试失败,请点击运行面板中的测试名称。选择屏幕截图标签页,使用集成的缩放和平移控件检查图片差异。

使用 Gradle 任务

运行验证任务以拍摄新的屏幕截图,并将其与参考图片进行比较:

  • Linux 和 macOS:./gradlew validateDebugScreenshotTest (./gradlew :{module}:validate{Variant}ScreenshotTest)
  • Windows:gradlew validateDebugScreenshotTest (gradlew :{module}:validate{Variant}ScreenshotTest)

验证任务会在 {module}/build/reports/screenshotTest/preview/{variant}/index.html 中创建一个 HTML 报告。

已知问题

  • Kotlin Multiplatform (KMP):IDE 和底层插件均专为 Android 项目而设计。它们不支持 KMP 项目中的非 Android 目标平台。
  • 重命名函数:重命名带有 @PreviewTest 注解的函数会破坏与现有参考图片的关联。在这种情况下,您必须为新函数名称重新生成参考图片

您可以在该工具的问题跟踪器组件中找到当前已知问题的完整列表。如需报告任何其他反馈和问题,请使用问题跟踪器

版本更新

0.0.1-alpha13

此版本引入了以下功能:

  • 与 JDK 17 或更高版本兼容。
  • 修复了多项 bug,并改进了与 Android Studio 的集成。

0.0.1-alpha12

此版本引入了以下功能:

  • 与 Android Gradle 插件 (AGP) 9.0 的兼容性。
  • 支持在 JDK 24 及更高版本上运行屏幕截图测试。
  • 支持配置最大堆大小。
  • 修复了渲染失败问题,并提高了测试稳定性。
  • 增强了报告功能,可显示百分比差异以及与新图片和参考图片相关的其他元数据。

0.0.1-alpha11

此版本引入了以下功能:

  • 与 Android Gradle 插件 (AGP) 8.13 的兼容性。
  • 添加了对解析具有十进制值的 XML 可绘制对象的支持,无论主机语言区域如何。
  • 对于使用 JDK 24 或更高版本的主机,系统会选择兼容的 JDK (11-23),前提是已安装了此类 JDK。

0.0.1-alpha10

此版本引入了以下功能:

  • 从这个版本开始,您需要使用 @PreviewTest 注解标记所有预览函数。不含注释的预览不会执行。

  • 参考图片目录已从 {module}/src/{variant}/screenshotTest/reference 更改为 {module}/src/screenshotTest{Variant}/reference。这是为了确保生成的参考图片不会成为生产代码的一部分,并与其他测试类型的目录结构保持一致。

  • {variant}PreviewScreenshotRender 任务会被移除。图片渲染已迁移到 JUnit 测试引擎中。

  • update{Variant}ScreenshotTest 任务会在更新之前将新的渲染图片与参考图片进行比较。它只会更新差异大于指定阈值的图片。移除了 --updateFilter 命令行标志。

0.0.1-alpha06

此版本引入了以下功能:

图片差异阈值:借助这项新的全局阈值设置,您可以更精细地控制屏幕截图比较。如需进行配置,请更新模块的 build.gradle.kts:

android {
    testOptions {
        screenshotTests {
            imageDifferenceThreshold = 0.0001f // 0.01%
        }
    }
}

此阈值将应用于模块中定义的所有屏幕截图测试。

  • 问题修复:修复了一些 Compose 渲染器 bug,并添加了对空 Compose 的支持
  • 性能增强:更新了图片差异比较算法,使其速度更快