AndroidJUnitRunner

The AndroidJUnitRunner class is a JUnit test runner that lets you run instrumented JUnit 4 tests on Android devices, including those using the Espresso, UI Automator, and Compose testing frameworks.

The test runner handles loading your test package and the app under test to a device, running your tests, and reporting test results.

This test runner supports several common testing tasks, including the following

Write JUnit tests

The following code snippet shows how you might write an instrumented JUnit 4 test to validate that the changeText operation in the ChangeTextBehavior class works correctly

Kotlin

@RunWith(AndroidJUnit4::class) // Only needed when mixing JUnit 3 and 4 tests
@LargeTest // Optional runner annotation
class ChangeTextBehaviorTest {
 val stringToBeTyped = "Espresso"
 // ActivityTestRule accesses context through the runner
 @get:Rule
 val activityRule = ActivityTestRule(MainActivity::class.java)

 @Test fun changeText_sameActivity() {
 // Type text and then press the button.
 onView(withId(R.id.editTextUserInput))
 .perform(typeText(stringToBeTyped), closeSoftKeyboard())
 onView(withId(R.id.changeTextBt)).perform(click())

 // Check that the text was changed.
 onView(withId(R.id.textToBeChanged))
 .check(matches(withText(stringToBeTyped)))
 }
}

Java

@RunWith(AndroidJUnit4.class) // Only needed when mixing JUnit 3 and 4 tests
@LargeTest // Optional runner annotation
public class ChangeTextBehaviorTest {

    private static final String stringToBeTyped = "Espresso";

    @Rule
    public ActivityTestRule<MainActivity>; activityRule =
            new ActivityTestRule<>;(MainActivity.class);

    @Test
    public void changeText_sameActivity() {
        // Type text and then press the button.
        onView(withId(R.id.editTextUserInput))
                .perform(typeText(stringToBeTyped), closeSoftKeyboard());
        onView(withId(R.id.changeTextBt)).perform(click());

        // Check that the text was changed.
        onView(withId(R.id.textToBeChanged))
                .check(matches(withText(stringToBeTyped)));
    }
}

Access the Application's Context

When you use AndroidJUnitRunner to run your tests, you can access the context for the app under test by calling the static ApplicationProvider.getApplicationContext() method. If you've created a custom subclass of Application in your app, this method returns your custom subclass's context.

If you're a tools implementer, you can access low-level testing APIs using the InstrumentationRegistry class. This class includes the Instrumentation object, the target app Context object, the test app Context object, and the command line arguments passed into your test.

Filter tests

In your JUnit 4.x tests, you can use annotations to configure the test run. This feature minimizes the need to add boilerplate and conditional code in your tests. In addition to the standard annotations supported by JUnit 4, the test runner also supports Android-specific annotations, including the following

  • @RequiresDevice: Specifies that the test should run only on physical devices, not on emulators.
  • @SdkSuppress: Suppresses the test from running on a lower Android API level than the given level. For example, to suppress tests on all API levels lower than 23 from running, use the annotation @SDKSuppress(minSdkVersion=23).
  • @SmallTest, @MediumTest, and @LargeTest: Classify how long a test should take to run, and consequently, how frequently you can run the test. You can use this annotation to filter which tests to run, setting the android.testInstrumentationRunnerArguments.size property
-Pandroid.testInstrumentationRunnerArguments.size=small

Shard tests

如果你需要并行执行测试,将测试分布在多个服务器上以加快执行速度,可以将测试分成组,或称为“分片”。测试运行器支持将单个测试套件拆分成多个分片,这样你就可以轻松地将属于同一分片的测试作为一组一起运行。每个分片都由一个索引号标识。运行测试时,使用 -e numShards 选项指定要创建的分片数量,并使用 -e shardIndex 选项指定要运行的分片。

例如,要将测试套件分成 10 个分片,并只运行第二个分片中的测试,请使用以下 adb 命令

adb shell am instrument -w -e numShards 10 -e shardIndex 2

使用 Android 测试协调器

Android 测试协调器允许你为应用程序的每个测试运行一个单独的 Instrumentation 实例。当使用 AndroidJUnitRunner 版本 1.0 或更高版本时,你就可以使用 Android 测试协调器。

Android 测试协调器为你的测试环境提供以下好处

  • 最小共享状态:每个测试都在其自己的 Instrumentation 实例中运行。因此,如果你的测试共享应用程序状态,则大多数共享状态会在每个测试之后从设备的 CPU 或内存中移除。若要在每个测试后从设备的 CPU 和内存中移除所有共享状态,请使用 clearPackageData 标志。有关示例,请参见 从 Gradle 启用 部分。
  • 崩溃隔离:即使一个测试崩溃,也只会导致其自己的 Instrumentation 实例停止运行。这意味着你的测试套件中的其他测试仍然可以运行,从而提供完整的测试结果。

这种隔离会导致测试执行时间的潜在增加,因为 Android 测试协调器会在每个测试之后重新启动应用程序。

Android Studio 和 Firebase Test Lab 都预装了 Android 测试协调器,不过你需要 在 Android Studio 中启用该功能

从 Gradle 启用

若要使用 Gradle 命令行工具启用 Android 测试协调器,请完成以下步骤

  • 步骤 1:修改 gradle 文件。在项目的 build.gradle 文件中添加以下语句
android {
 defaultConfig {
  ...
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

  // The following argument makes the Android Test Orchestrator run its
  // "pm clear" command after each test invocation. This command ensures
  // that the app's state is completely cleared between tests.
  testInstrumentationRunnerArguments clearPackageData: 'true'
 }

 testOptions {
  execution 'ANDROIDX_TEST_ORCHESTRATOR'
 }
}

dependencies {
 androidTestImplementation 'androidx.test:runner:1.1.0'
 androidTestUtil 'androidx.test:orchestrator:1.1.0'
}
  • 步骤 2:通过执行以下命令运行 Android 测试协调器
./gradlew connectedCheck

从 Android Studio 启用

若要在 Android Studio 中启用 Android 测试协调器,请将 从 Gradle 启用 中显示的语句添加到应用程序的 build.gradle 文件中。

从命令行启用

若要在命令行上使用 Android 测试协调器,请在终端窗口中运行以下命令

DEVICE_API_LEVEL=$(adb shell getprop ro.build.version.sdk)

FORCE_QUERYABLE_OPTION=""
if [[ $DEVICE_API_LEVEL -ge 30 ]]; then
   FORCE_QUERYABLE_OPTION="--force-queryable"
fi

# uninstall old versions
adb uninstall androidx.test.services
adb uninstall androidx.test.orchestrator

# Install the test orchestrator.
adb install $FORCE_QUERYABLE_OPTION -r path/to/m2repository/androidx/test/orchestrator/1.4.2/orchestrator-1.4.2.apk

# Install test services.
adb install $FORCE_QUERYABLE_OPTION -r path/to/m2repository/androidx/test/services/test-services/1.4.2/test-services-1.4.2.apk

# Replace "com.example.test" with the name of the package containing your tests.
# Add "-e clearPackageData true" to clear your app's data in between runs.
adb shell 'CLASSPATH=$(pm path androidx.test.services) app_process / \
 androidx.test.services.shellexecutor.ShellMain am instrument -w -e \
 targetInstrumentation com.example.test/androidx.test.runner.AndroidJUnitRunner \
 androidx.test.orchestrator/.AndroidTestOrchestrator'

如命令语法所示,首先安装 Android 测试协调器,然后直接使用它。

adb shell pm list instrumentation

使用不同的工具链

如果你使用不同的工具链测试应用程序,仍然可以通过完成以下步骤使用 Android 测试协调器

  1. 在应用程序的构建文件中包含必要的
  2. 命令行 启用 Android 测试协调器。

架构

协调器服务 APK 存储在一个与测试 APK 和被测试应用程序的 APK 分开的进程中

The orchestrator allows you to control JUnit tests
图 1:Android 测试协调器 APK 结构。

Android 测试协调器在你的测试套件运行开始时收集 JUnit 测试,但随后会单独执行每个测试,在自己的 Instrumentation 实例中。

更多信息

若要详细了解如何使用 AndroidJUnitRunner,请参见 API 参考

其他资源

有关如何使用 AndroidJUnitRunner 的更多信息,请查阅以下资源。

示例