从命令行进行测试

本文档介绍了如何直接通过命令行运行测试。本文假定您已经知道如何创建 Android 应用并为应用编写测试。如需详细了解如何为应用构建测试,请参阅在 Android 平台上测试应用。

本页面介绍的命令行工具和 Gradle 任务与界面工具包无关。如需为 Compose 编写界面测试,请参阅 测试 Compose 布局。编写完测试后,请继续阅读本指南,了解如何从终端或远程持续集成环境中运行测试。

当您使用 Gradle 构建��统构建应用时,Android Gradle 插件可让您使用命令行从 Gradle 项目运行测试。若想实现更精细的控制,您可以选择通过 Android 调试桥 (adb) shell 运行测试。在持续集成环境中运行测试时,此功能非常有用。

如需了解如何使用 Gradle 为您管理的虚拟设备从命令行运行自动插桩测试,请参阅使用 Gradle 管理的设备来扩展测试。

使用 Gradle 运行测试

借助 Android Gradle 插件,您可以使用命令行从 Gradle 项目运行测试。

下表总结了如何使用 Gradle 运行测试:

表 1. 使用 Gradle 运行测试的不同方法

单元测试类型 要运行的命令 测试结果位置
本地单元测试 运行 test 任务:

./gradlew test
HTML 测试结果文件:
path_to_your_project/module_name/build/reports/tests/ 目录。

XML 测试结果文件:
path_to_your_project/module_name/build/test-results/ 目录。

插桩单元测试 运行 connectedAndroidTest 任务:

./gradlew connectedAndroidTest
HTML 测试结果文件:
path_to_your_project/module_name/build/reports/androidTests/connected/ 目录。

XML 测试结果文件:
path_to_your_project/module_name/build/outputs/androidTest-results/connected/ 目录。

Gradle 支持任务名称缩写。例如,如果您输入以下命令,便可启动 connectedAndroidTest 任务:

./gradlew cAT

您还可以选择运行 Gradle 任务 check 和 connectedCheck。这些任务分别运行您的本地测试或插桩测试,但包含其他 Gradle 插件添加的其他检查。

在模块上运行测试

test 和 connectedAndroidTest 任务会在项目中的每个模块上运行测试。您可以在 test 或 connectedAndroidTest 任务前加上模块名称和英文冒号 (:),以针对特定模块运行测试。例如,以下命令仅针对 mylibrary 模块运行插桩测试:

./gradlew mylibrary:connectedAndroidTest

对 build 变体运行测试

test 和 connectedAndroidTest 任务会针对项目中的每个 build 变体运行测试。您可以使用以下语法指定特定的 build 变体:

  • 对于本地单元测试:
    ./gradlew testVariantNameUnitTest
  • 对于插桩测试:
    ./gradlew connectedVariantNameAndroidTest

运行特定的测试方法或类

运行本地单元测试时,Gradle 允许您使用 --tests 标记指定特定的测试。例如,以下命令仅针对指定的 build 变体运行 sampleTestMethod 测试。要详细了解如何 使用 --tests 标记,请参阅关于 测试过滤的 Gradle 文档。


./gradlew testVariantNameUnitTest --tests '*.sampleTestMethod'

使用 adb 运行测试

当您使用 Android 调试桥 (adb) 从命令行运行测试时,您可以获得比任何其他方法更多的选项来选择要运行的测试。您可以选择单独的测试方法,根据自定义注解筛选测试,或指定测试选项。由于测试任务完全由命令行控制,因此您可以通过各种方式使用 Shell 脚本自定义测试。

若想通过命令行运行测试,请运行 adb shell 以在设备或模拟器上启动命令行 shell。在该 shell 中,您可以使用 activity 管理器 与 activity 管理器进行交互,并使用其 am 命令和 instrument 子命令运行测试。

作为一种快捷方式,您可以在同一个输入行上启动 adb shell,调用 am instrument 和指定命令行 flag。shell 会在设备或模拟器上打开,运行测试,生成输出,然后返回到计算机上的命令行。

要使用 am instrument 运行测试,请执行以下操作:

  1. 构建或重新构建主应用和 测试软件包。
  2. 安装您的测试软件包和主 应用 Android 软件包文件(APK 文件)到当前的 Android 设备或模拟器中。
  3. 在命令行中,输入:

    adb shell am instrument -w <test_package_name>/<runner_class>

    其中,<test_package_name> 是测试应用的 Android 软件包名称,<runner_class> 是您正在使用的 Android 测试运行程序类的名称。Android 软件包名称是测试软件包的清单文件 (AndroidManifest.xml) 中清单元素的软件包属性的值。

    Android 测试运行程序类通常是 AndroidJUnitRunner:

    adb shell am instrument -w com.android.example/androidx.test.runner.AndroidJUnitRunner

测试结果会显示在 STDOUT 中。

am instrument 标记

如需查找与 am instrument 命令搭配使用的所有标记的列表,请运行 adb shell am help。下表介绍了一些重要标记:

表 2. 重要的 am instrument 标记

标记 值 说明
-w (无) 强制 am instrument 一直等到插桩终止后再终止自身。这样可在测试完成前使 shell 一直保持打开状态。必须使用此标记,才能看到测试结果。
-r (无) 原始格式的输出结果。如果要收集性能测量值,请使用此标记,这样系统就不会将它们的格式设置为 测试结果。此标记应与标记 -e perf true(如 am instrument options 选项部分中所述)一起使用。
-e <test_options> 提供键值对形式的测试选项。am instrument 工具会通过其 onCreate() 方法将这些选项传递给指定的插桩类。您可以指定 -e <test_options> 多次。键和值在 am instrument options 选项部分中进行了介绍。您只能将这些键值对用于 AndroidJUnitRunner。 将这些键值对用于任何其他类没有任何作用。
--no-hidden-api-checks (无) 停用对使用隐藏 API 的限制。如需详细了解什么是隐藏 API 以及这会对您的应用产生什么影响,请参阅对非 SDK 接口的限制。

am instrument 选项

am instrument 工具使用 -e 标记以键值对的形式将测试选项传递给 AndroidJUnitRunner 或 InstrumentationTestRunner,语法如下:

-e <key> <value>

某些键接受多个值。您可以在英文逗号分隔列表中指定多个值。例如,以下 AndroidJUnitRunner 调用为 package 键提供了多个值:

adb shell am instrument -w -e package com.android.test.package1,com.android.test.package2 \
> com.android.test/androidx.test.runner.AndroidJUnitRunner

下表列出了可针对测试运行程序使用的键值对:

表 3. 可与测试运行程序搭配使用的 -e 标记键值对

键 值 说明
package <Java_package_name> 测试应用中某个软件包的完全限定 Java 软件包名称。系统会执行使用此软件包名称的所有测试用例类。请注意,这不是 Android 软件包名称;测试软件包只有一个 Android 软件包名称,但其中可能包含多个 Java 软件包。
class <class_name> 其中一个测试用例类的完全限定 Java 类名称。系统仅会执行此测试用例类。
<class_name>#method name 完全限定测试用例类名称及其方法之一。系统仅会执行此方法。注意类名 和方法名之间的哈希标记 (#)。
size [small | medium | large] 运行按大小注解的测试方法。注解为 @SmallTest、@MediumTest 和 @LargeTest。
debug true 在调试模式下运行测试。
log true 加载并记录所有指定的测试,但不运行它们。测试信息会显示在 STDOUT 中。使用此选项可验证其他过滤器和测试规范的组合。
emma true 运行 EMMA 代码覆盖率分析并将输出写入设备上的 /data/<app_package>/coverage.ec。要替换文件位置,请使用以下条目中所述的 coverageFile 键。

注意:此选项需要对测试应用进行 EMMA 插桩 build,您可以使用 coverage 目标生成该 build。

coverageFile <filename> 替换设备上 EMMA 覆盖率文件的默认位置。将此值指定为 UNIX 格式的路径和文件名。emma 键的条目中描述了默认文件名。

使用 -e 标记时,请注意以下事项:

  • am instrument 会在调用 onCreate(Bundle) 时传入包含键值对的 Bundle。
  • package 键优先于 class 键。如果您指定了一个软件包,然后在该软件包中单独指定一个类,Android 将运行该软件包中的所有测试并忽略类键。
  • func 键和 unit 键是互斥的。

用法示例

以下部分提供了使用 am instrument 运行测试的示例。它们基于以下结构:

  • 测试软件包的 Android 软件包名称为 com.android.demo.app.tests。
  • 两个插桩测试类:
    • TestClass1(包含测试方法 testMethod1)。
    • TestClass2(包含测试方法 testMethod2 和 testMethod3)。
  • 测试运行程序为 AndroidJUnitRunner。

运行整个测试软件包

要运行测试软件包中的所有测试类,请输入:

adb shell am instrument -w com.android.demo.app.tests/androidx.test.runner.AndroidJUnitRunner

运行测试用例类中的所有测试

要运行 TestClass1 类中的所有测试,请输入:

adb shell am instrument -w  \
> -e class com.android.demo.app.tests.TestClass1 \
> com.android.demo.app.tests/androidx.test.runner.AndroidJUnitRunner

选择一部分测试

如需运行 TestClass1 类中的所有测试以及 TestClass2 中的 testMethod3 方法,请输入:

adb shell am instrument -w \
> -e class com.android.demo.app.tests.TestClass1,com.android.demo.app.tests.TestClass2#testMethod3 \
> com.android.demo.app.tests/androidx.test.runner.AndroidJUnitRunner

您可以在 AndroidJUnitRunner API 参考文档中找到更多用例。

查看统一的测试报告

Android Gradle 插件提供了统一的测试任务,这些任务会生成 HTML 信息中心,用于合并单元测试和插桩测试的结果。

前提条件

  • Android Gradle 插件 9.5.0-alpha05 或更高版本。

如需测试所有测试套件,请运行以下任务之一:

报告范围 命令 说明 报告位置
当前模块 ./gradlew :module_name:testAllSuites --continue 为当前模块生成统一的测试报告,合并单元测试和插桩测试结果。 path_to_your_project/module_name/build/reports/testAllSuites/test-report/
当前模块和依赖项 ./gradlew :module_name:testAllSuitesWithDependencies --continue 为当前模块及其库依赖项生成统一的测试报告,合并单元测试和插桩测试结果。 path_to_your_project/module_name/build/reports/testAllSuitesWithDependencies/test-report/