构建管理的设备 (build-managed devices) 可提高您自动化测试的一致性、性能和可靠性。此功能适用于 API 级别 27 及更高版本,允许您在项目的 Gradle 文件中配置虚拟或远程物理测试设备。Android Gradle 插件会使用这些配置来全面管理(即创建、部署和销毁)执行自动化测试时的设备。
此功能不仅让 Android Gradle 插件能够洞察您运行的测试,还能监控设备的生命周期,从而通过以下方式提升您的测试体验:
- 处理设备相关问题,以确保您的测试能够执行
- 对于虚拟设备,使用模拟器快照来缩短设备启动时间、优化内存使用,并在测试之间将设备恢复到干净状态
- 缓存测试结果,并仅重新运行可能产生不同结果的测试
- 为本地和远程测试运行提供一致的测试环境
创建虚拟构建管理设备
您可以在模块级构建文件中指定用于测试应用程序的虚拟设备。以下代码示例创建了一个运行 API 级别 30 的 Pixel 2,作为构建管理的设备。
Kotlin
android { testOptions { managedDevices { localDevices { create("pixel2api30") { // Use device profiles you typically see in Android Studio. device = "Pixel 2" // Use only API levels 27 and higher. apiLevel = 30 // To include Google services, use "google". systemImageSource = "aosp" } } } } }
Groovy
android { testOptions { managedDevices { localDevices { pixel2api30 { // Use device profiles you typically see in Android Studio. device = "Pixel 2" // Use only API levels 27 and higher. apiLevel = 30 // To include Google services, use "google". systemImageSource = "aosp" } } } } }
定义设备组
为了帮助您跨多个设备配置(例如不同的 API 级别和外观尺寸)扩展测试,您可以定义多个构建管理的设备,并将它们添加到命名组中。随后,Android Gradle 插件可以并行执行组内所有设备上的测试。
下面的示例展示了添加到名为 phoneAndTablet 的设备组中的两个设备。
Kotlin
testOptions { managedDevices { localDevices { create("pixel2api29") { ... } create("nexus9api30") { ... } } groups { create("phoneAndTablet") { targetDevices.add(devices["pixel2api29"]) targetDevices.add(devices["nexus9api30"]) } } } }
Groovy
testOptions { managedDevices { localDevices { pixel2api29 { ... } nexus9api30 { ... } } groups { phoneAndTablet { targetDevices.add(devices.pixel2api29) targetDevices.add(devices.nexus9api30) } } } }
运行测试
要使用您配置的构建管理设备运行测试,请使用以下命令。device-name 是您在 Gradle 构建脚本中配置的设备名称(例如 pixel2api30),BuildVariant 是您想要测试的应用构建变体,例如 Debug。
Linux 和 macOS
./gradlew device-nameBuildVariantAndroidTest
Windows
gradlew device-nameBuildVariantAndroidTest
要在设备组上运行测试,请使用以下命令。
Linux 和 macOS
./gradlew group-nameGroupBuildVariantAndroidTest
./gradlew group-nameGroupBuildVariantAndroidTest
Windows
gradlew group-nameGroupBuildVariantAndroidTest
测试输出包含指向测试报告 HTML 文件的路径。您还可以通过点击 IDE 中的 Run > Test History,将测试结果导入 Android Studio 以进行进一步分析。
启用测试分片 (Test Sharding)
构建管理的设备支持测试分片,这允许您将测试套件拆分到多个并行的相同虚拟设备实例(称为分片)上运行。使用测试分片有助于减少整体测试执行时间,但会消耗额外的计算资源。
要设置在特定测试运行中使用的分片数量,请在您的 gradle.properties 文件中进行如下设置:
android.experimental.androidTest.numManagedDeviceShards=<number_of_shards>
当使用此选项运行测试时,构建管理的设备会为测试运行中的每个设备配置文件预配您指定的分片数量。例如,如果您将测试部署到包含三台设备的设备组,并将 numManagedDeviceShards 设置为 2,那么构建管理的设备总共将为您的测试运行预配六台虚拟设备。
测试完成后,Gradle 会为测试运行中使用的每个分片输出一个 .proto 格式的测试结果文件。
使用自动化测试设备 (ATD)
构建管理的设备支持一种称为“自动化测试设备”(ATD) 的模拟器类型,它经过优化,可在运行检测测试时减少 CPU 和内存资源占用。ATD 通过以下方式提高运行时性能:
- 移除通常对测试应用无用的预装应用
- 禁用通常对测试应用无用的某些后台服务
- 禁用硬件渲染
开始之前,请确保您已将 Android 模拟器更新到最新版本。然后,在模块级构建文件中定义构建管理设备时指定 "-atd" 映像,如下所示:
Kotlin
android { testOptions { managedDevices { localDevices { create("pixel2api30") { // Use device profiles you typically see in Android Studio. device = "Pixel 2" // ATDs currently support only API level 30. apiLevel = 30 // You can also specify "google-atd" if you require Google Play Services. systemImageSource = "aosp-atd" } } } } }
Groovy
android { testOptions { managedDevices { localDevices { pixel2api30 { // Use device profiles you typically see in Android Studio. device = "Pixel 2" // ATDs currently support only API level 30. apiLevel = 30 // You can also specify "google-atd" if you require Google Play Services. systemImageSource = "aosp-atd" } } } } }
与其它构建管理设备一样,您也可以创建设备组。为了进一步利用性能提升,您还可以将 ATD 与测试分片结合使用,以缩短测试套件的总执行时间。
ATD 映像中移除了哪些内容?
除了以无头 (headless) 模式运行外,ATD 还通过移除或禁用测试应用代码通常不需要的应用程序和服务来优化性能。下表概述了我们在 ATD 映像中移除或禁用的组件,并说明了为什么它们在测试中可能不是必需的。
| ATD 映像中移除的内容 | 运行自动化测试时为何不需要这些内容 |
|---|---|
Google 产品应用
|
您的自动化测试应专注于您自己的应用逻辑,并假设其他应用或平台能够正常工作。 使用 Espresso-Intents,您可以匹配和验证传出意图 (intent),甚至可以提供存根响应来代替实际的意图响应。 |
设置应用和服务
|
这些应用为最终用户提供了更改平台设置、设置设备或管理存储空间的图形界面。这通常超出了应用级自动化测试的范围。
|
| SystemUI | 您的自动化测试应专注于您自己的应用逻辑,并假设其他应用或平台能够正常工作。 |
AOSP 应用和服务
|
这些应用和服务通常超出了应用代码自动化测试的范围。 |
使用 Firebase Test Lab 设备
使用构建管理的设备时,您可以在 Firebase Test Lab 设备上大规模运行自动化检测测试。Test Lab 允许您在各种 Android 设备(物理设备和虚拟设备)上同时运行测试。这些测试在 Google 的远程数据中心运行。在构建管理设备的支持下,构建系统可以根据您的配置全面管理针对这些 Test Lab 设备的测试运行。
开始使用
以下步骤介绍了如何开始将 Firebase Test Lab 设备与构建管理的设备结合使用。这些步骤使用 gcloud CLI 提供用户凭据,这可能并不适用于所有开发环境。有关适合您需求的身份验证流程的更多信息,请参阅 应用程序默认凭据的工作原理。
要创建 Firebase 项目,请前往 Firebase 控制台。点击 添加项目 并按照屏幕提示创建项目。请记住您的项目 ID。
要安装 Google Cloud CLI,请按照 安装 gcloud CLI 中的步骤操作。
配置本地环境。
在 gcloud 中关联您的 Firebase 项目
gcloud config set project FIREBASE_PROJECT_ID
授权使用您的用户凭据进行 API 访问。我们建议通过在模块级构建脚本中使用 DSL 将 服务账号 JSON 文件 传递给 Gradle 来进行授权。
Kotlin
firebaseTestLab { ... serviceAccountCredentials.set(file(SERVICE_ACCOUNT_JSON_FILE)) }
Groovy
firebaseTestLab { ... serviceAccountCredentials = file(SERVICE_ACCOUNT_JSON_FILE) }
或者,您可以使用以下终端命令手动进行授权
gcloud auth application-default login
可选:将您的 Firebase 项目添加为配额项目。仅当您超过 Test Lab 的免费配额时才需要此步骤。
gcloud auth application-default set-quota-project FIREBASE_PROJECT_ID
启用所需的 API。
在 Google Developers Console API 库页面中,通过在控制台顶部的搜索框中输入 API 名称,然后点击每个 API 概览页面上的 启用 API,来启用 Cloud Testing API 和 Cloud Tool Results API。
配置您的 Android 项目。
在顶级构建脚本中添加 Firebase Test Lab 插件
Kotlin
plugins { ... id("com.google.firebase.testlab") version "0.0.1-alpha05" apply false }
Groovy
plugins { ... id 'com.google.firebase.testlab' version '0.0.1-alpha05' apply false }
在
gradle.properties文件中启用自定义设备类型android.experimental.testOptions.managedDevices.customDevice=true
在模块级构建脚本中添加 Firebase Test Lab 插件
Kotlin
plugins { ... id "com.google.firebase.testlab" }
Groovy
plugins { ... id 'com.google.firebase.testlab' }
指定 Test Lab 设备
您可以在模块级构建脚本中指定 Gradle 用于测试应用的 Firebase Test Lab 设备。以下代码示例创建了一个运行 API 级别 30 的 Pixel 3,作为名为 ftlDevice 的构建管理 Test Lab 设备。firebaseTestLab {} 块在将 com.google.firebase.testlab 插件应用于模块时可用。
Kotlin
firebaseTestLab { managedDevices { create("ftlDevice") { device = "Pixel3" apiLevel = 30 } } ... }
Groovy
firebaseTestLab { managedDevices { ftlDevice { device = "Pixel3" apiLevel = 30 } } ... }
要定义包含 Firebase Test Lab 设备的构建管理设备组,请参阅 定义设备组。
要运行测试,请使用与运行其他构建管理设备相同的命令。请注意,Gradle 不会并行运行测试,也不支持 Test Lab 设备的其它 Google Cloud CLI 配置。
通过智能分片优化测试运行
在构建管理的 Test Lab 设备上进行测试支持“智能分片”。智能分片会自动将测试分发到各个分片,使每个分片的运行时间大致相同,从而减少手动分配的工作量并缩短整体测试运行时间。智能分片使用您的测试历史记录或关于测试之前运行所需时间的信息,以最优方式分配测试。请注意,您需要 Firebase Test Lab 的 Gradle 插件版本 0.0.1-alpha05 才能使用智能分片。
要启用智能分片,请指定每个分片内测试应持续的时间。您应该将目标分片持续时间设置为至少比 timeoutMinutes 少五分钟,以避免在测试完成前分片被取消的情况。
firebaseTestLab { ... testOptions { targetedShardDurationMinutes = 2 } }
要了解更多信息,请阅读关于 Firebase Test Lab 设备 DSL 选项的内容。
Test Lab 设备的更新版 DSL
您可以配置更多 DSL 选项来帮助自定义测试运行,或从您可能已经使用的其他解决方案迁移过来。请查看以下代码片段中描述的一些选项。
firebaseTestLab { ... /** * A path to a JSON file that contains service account credentials to access to * a Firebase Test Lab project. */ serviceAccountCredentials.set(file("your_service_account_credentials.json")) testOptions { fixture { /** * Whether to grant permissions on the device before tests begin. * Available options are "all" or "none". * * Default value is "all". */ grantedPermissions = "all" /** * Map of files to push to the device before starting the test. * * The key is the location on the device. * The value is the location of the file, either local or in Google Cloud. */ extraDeviceFiles["/sdcard/dir1/file1.txt"] = "local/file.txt" extraDeviceFiles["/sdcard/dir2/file2.txt"] = "gs://bucket/file.jpg" /** * The name of the network traffic profile. * * Specifies network conditions to emulate when running tests. * * Default value is empty. */ networkProfile = "LTE" } execution { /** * The maximum time to run the test execution before cancellation, * measured in minutes. Does not include the setup or teardown of device, * and is handled server-side. * * The maximum possible testing time is 45 minutes on physical devices * and 60 minutes on virtual devices. * * Defaults to 15 minutes. */ timeoutMinutes = 30 /** * Number of times the test should be rerun if tests fail. * The number of times a test execution should be retried if one * or more of its test cases fail. * * The max number of times is 10. * * The default number of times is 0. */ maxTestReruns = 2 /** * Ensures only a single attempt is made for each execution if * an infrastructure issue occurs. This doesn't affect `maxTestReruns`. * Normally, two or more attempts are made by Firebase Test Lab if a * potential infrastructure issue is detected. This is best enabled for * latency sensitive workloads. The number of execution failures might be * significantly greater with `failFast` enabled. * * Defaults to false. */ failFast = false /** * The number of shards to split the tests across. * * Default to 0 for no sharding. */ numUniformShards = 20 } /** * For smart sharding, the target length of time each shard should takes in * minutes. Maxes out at 50 shards for physical devices and 100 shards for * virtual devices. * * Only one of numUniformShards or targetedShardDurationMinutes can be set. * * Defaults to 0 for no smart sharding. */ targetedShardDurationMinutes = 15 } results { /** * The name of the Google storage bucket to store the test results in. * * If left unspecified, the default bucket is used. * * Please refer to Firebase Test Lab permissions for required permissions * for using the bucket. */ cloudStorageBucket = "bucketLocationName" /** * Name of test results for the Firebase console history list. * All tests results with the same history name are grouped * together in the Firebase console in a time-ordered test history list. * * Defaults to the application label in the APK manifest. */ resultsHistoryName = "application-history" /** * List of paths to copy from the test device's storage to the test * results folder. These must be absolute paths under /sdcard or * /data/local/tmp. */ directoriesToPull.addAll( "/sdcard/path/to/something" ) /** * Whether to enable video recording during the test. * * Disabled by default. */ recordVideo = false /** * Whether to enable performance metrics. If enabled, monitors and records * performance metrics such as CPU, memory, and network usage. * * Defaults to false. */ performanceMetrics = true } }