从命令行进行测试

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

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

当您使用 Gradle 构建系统构建应用时,Android Gradle 插件可让您使用命令行从 Gradle 项目运行测试。若想实现更精细的控制,您还可以选择通过 Android 调试桥 (adb) shell 运行测试。

使用 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 任务 checkconnectedCheck。这些任务分别运行您的本地测试或插桩测试,但还包含其他 Gradle 插件添加的其他检查。

在模块上运行测试

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

./gradlew mylibrary:connectedAndroidTest

对 build 变体运行测试

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

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

运行特定的测试方法或类

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


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

针对插桩测试的多模块报告

如表 1 所述,Gradle 会将插桩测试结果保存在它测试的每个模块的 build/ 目录中。但是,在对多个模块运行测试时,将所有测试结果合并到一个报告中可能很有用。要在对多个模块运行测试时生成一个报告,请按以下步骤操作:

  1. 在项目级 build.gradle 文件中,在 buildscript{} 代码块后添加以下代码:

    Groovy

    apply plugin 'android-reporting'
    

    Kotlin

    apply(plugin = "android-reporting")
    
  2. 使用 mergeAndroidReports 任务调用 testconnectedAndroidTest 任务。例如:

    ./gradlew connectedAndroidTest mergeAndroidReports
    

    如果要跳过测试失败的情况以便让 Gradle 运行完所有剩余测试,请添加 --continue 选项:

    ./gradlew connectedAndroidTest mergeAndroidReports --continue
    

当 Gradle 运行完所有测试后,它会将合并的结果保存在 path_to_your_project/build/ 目录中。

使用 adb 运行测试

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

若想通过命令行运行测试,请运行 adb shell 以在设备或模拟器上启动命令行 shell。在该 shell 中,您可以使用 am 命令与 Activity 管理器进行交互,并使用其 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.foo/androidx.test.runner.AndroidJUnitRunner
    

测试结果会显示在 STDOUT 中。

am instrument 标记

您可以通过运行 adb shell am help 找到与 am instrument 命令搭配使用的所有标记的列表。下表介绍了一些重要标记:

表 2. 重要的 am instrument 标记。

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

am instrument 选项

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

-e <key> <value>

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

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

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

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

说明
package <Java_package_name> 测试应用中某个软件包的完全限定 Java 软件包名称。系统会执行使用此软件包名称的所有测试用例类。请注意,这不是 Android 软件包名称;测试软件包只有一个 Android 软件包名称,但其中可能包含多个 Java 软件包。
class <class_name> 其中一个测试用例类的完全限定 Java 类名称。系统仅会执行此测试用例类。
<class_name>#method name 完全限定测试用例类名称及其方法之一。系统仅会执行此方法。注意类名和方法名之间的哈希标记 (#)。
func true 运行扩展 InstrumentationTestCase 的所有测试类。
unit true 运行没有扩展 InstrumentationTestCasePerformanceTestCase 的所有测试类。
size [small | medium | large] 运行按大小注解的测试方法。注解为 @SmallTest@MediumTest@LargeTest
perf true 运行所有实现 PerformanceTestCase 的测试类。使用此选项时,还要为 am instrument 指定 -r 标记,以原始格式保存输出,而不重新调整为测试结果。
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
  • 两个插桩测试类:
    • Foo1(包含测试方法 bar1)和
    • Foo2(包含测试方法 bar2bar3
  • 测试运行程序为 AndroidJUnitRunner

运行整个测试软件包

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

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

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

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

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

选择一部分测试

如需运行 Foo1 类中的所有测试以及 Foo2 中的 bar3 方法,请输入:

adb shell am instrument -w \
> -e class com.android.demo.app.tests.Foo1,com.android.demo.app.tests.Foo2#bar3 \
> com.android.demo.app.tests/android.support.test.runner.AndroidJUnitRunner

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