高级测试设置

在 Android Studio 中进行测试从命令行进行测试页面介绍了如何设置并运行基本测试配置。但是,如果您的应用及其测试要求越来越高级,您可能需要进一步调整测试配置。例如,如果您想执行以下操作,可能需要用到高级测试设置:

  • 仅针对特定 build 变体运行插桩测试,或替换其清单设置。
  • 更改用于运行测试的 build 类型,或配置其 Gradle 选项。
  • 将插桩测试提取到各自的测试模块中。

本页面将介绍当默认设置不适合当前用例时配置测试的各种方法。

为 build 变体创建插桩测试

如果您的项目包含的 build 变体具有专属的源代码集,您可能希望包含与这些源代码集对应的插桩测试。这样有助于保持测试代码的条理性,并可以仅运行适用于给定 build 变体的测试。

您可以将插桩测试关联到 build 变体,方法是将它们放在自己的源代码集(位于 src/androidTestVariantName)中。

src/androidTest/ 源代码集中的插桩测试适用于所有 build 变体。为应用的“MyFlavor”变体构建测试 APK 时,Gradle 会将 src/androidTest/src/androidTestMyFlavor/ 这两个源代码集合并。

如需在 Android Studio 中为 build 变体添加测试源代码集,请按以下步骤操作:

  1. 在左侧的 Project 窗口中,点击下拉菜单并选择 Project 视图。
  2. 在相应的模块文件夹内,右键点击 src 文件夹,然后依次点击 New > Directory
  3. 对于目录名称,请输入“androidTestVariantName”。例如,如果您有一个名为“MyFlavor”的 build 变体,则目录名称应为“androidTestMyFlavor”。然后点击 OK
  4. 右键点击新目录,然后依次点击 New > Directory
  5. 输入“java”作为目录名,然后点击 OK

现在您就可以按照上述添加新测试的步骤向这个新源代码集添加测试了。当您看到 Choose Destination Directory 对话框时,请选择新的变体测试源代码集。

下表显示了一个示例,展示插桩测试文件如何位于与应用代码源代码集对应的源代码集中。

表 1. 应用源代码和相应的插桩测试文件。

应用类的路径 对应插桩测试类的路径
src/main/java/Foo.java src/androidTest/java/AndroidFooTest.java
src/myFlavor/java/Foo.java src/androidTestMyFlavor/java/AndroidFooTest.java

Gradle 构建系统会合并和替换来自不同测试源代码集的文件,就像它对应用源代码集的处理方法一样。在本示例中,androidTestMyFlavor 源代码集内的 AndroidFooTest.java 文件会替换 androidTest 源代码集内的版本。原因在于产品变种源代码集的优先级高于主源代码集。如需详细了解如何合并源代码集,请参阅配置 build

配置插桩测试清单设置

插桩测试内置于单独的 APK 中,拥有自己的 AndroidManifest.xml 文件。Gradle 在构建测试 APK 时,会自动生成 AndroidManifest.xml 文件,并为其配置 <instrumentation> 节点。Gradle 为您配置此节点的原因之一是,确保 targetPackage 属性指定了受测应用的正确软件包名称。您可以通过以下方式更改此节点的某些其他设置:在测试源代码集内再创建一个清单文件,或配置模块级 build.gradle 文件,如以下代码示例所示。您可以在 BaseFlavor API 参考文档中找到完整的选项列表。

android {

    ...

    // Each product flavor you configure can override properties in the
    // defaultConfig {} block. To learn more, go to Configure product flavors.

    defaultConfig {

        ...

        // Specifies the application ID for the test APK.
        testApplicationId = "com.test.foo"

        // Specifies the fully-qualified class name of the test instrumentation
        // runner.
        testInstrumentationRunner = "android.test.InstrumentationTestRunner"

        // If set to true, enables the instrumentation class to start and stop profiling.
        // If set to false (default), profiling occurs the entire time the instrumentation
        // class is running.
        testHandleProfiling = true

        // If set to true, indicates that the Android system should run the instrumentation
        // class as a functional test. The default value is false.
        testFunctionalTest = true

    }
}

更改测试 build 类型

默认情况下,所有插桩测试都会针对 debug build 类型运行。您可以使用模块级 build.gradle 文件中的 testBuildType 属性将其更改为针对其他 build 类型运行。例如,如果您想针对 staging build 类型运行测试,请按下面这段代码中所示对该文件进行编辑。

android {

    ...

    testBuildType "staging"

}

配置 Gradle 测试选项

借助 Android Gradle 插件,您可以为全部或部分测试指定特定选项。在模块级 build.gradle 文件中,可以使用 testOptions{} 代码块指定相关选项来更改 Gradle 运行所有测试的方式。

Groovy

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        // Changes the directory where Gradle saves test reports. By default,
        // Gradle saves test reports in the
        // path_to_your_project/module_name/build/outputs/reports/ directory.
        // '$rootDir' sets the path relative to the root directory of the
        // current project.
        reportDir "$rootDir/test-reports"
        // Changes the directory where Gradle saves test results. By default,
        // Gradle saves test results in the
        // path_to_your_project/module_name/build/outputs/test-results/ directory.
        // '$rootDir' sets the path relative to the root directory of the
        // current project.
        resultsDir "$rootDir/test-results"
    }
}

Kotlin

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        // Changes the directory where Gradle saves test reports. By default,
        // Gradle saves test reports in the
        // path_to_your_project/module_name/build/outputs/reports/ directory.
        // '$rootDir' sets the path relative to the root directory of the
        // current project.
        reportDir "$rootDir/test-reports"
        // Changes the directory where Gradle saves test results. By default,
        // Gradle saves test results in the
        // path_to_your_project/module_name/build/outputs/test-results/ directory.
        // '$rootDir' sets the path relative to the root directory of the
        // current project.
        resultsDir = "$rootDir/test-results"
    }
}

如需仅为本地单元测试指定选项,请配置 testOptions{} 中的 unitTests{} 代码块。

Groovy

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            // By default, local unit tests throw an exception any time the code
            // you are testing tries to access Android platform APIs (unless you
            /// mock Android dependencies yourself or with a testing framework like Mockito).
            // However, you can enable the following property so that the test
            // returns either null or zero when accessing platform APIs, rather
            // than throwing an exception.
            returnDefaultValues true

            // Encapsulates options for controlling how Gradle executes local
            // unit tests. For a list of all the options you can specify, read
            // Gradle's reference documentation.
            all {
                // Sets JVM argument(s) for the test JVM(s).
                jvmArgs '-XX:MaxPermSize=256m'

                // You can also check the task name to apply options to only the
                // tests you specify.
                if (it.name == 'testDebugUnitTest') {
                    systemProperty 'debug', 'true'
                }
                ...
            }
        }
    }
}

Kotlin

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            // By default, local unit tests throw an exception any time the code
            // you are testing tries to access Android platform APIs (unless you
            /// mock Android dependencies yourself or with a testing framework like Mockito).
            // However, you can enable the following property so that the test
            // returns either null or zero when accessing platform APIs, rather
            // than throwing an exception.
            returnDefaultValues = true

            // Encapsulates options for controlling how Gradle executes local
            // unit tests. For a list of all the options you can specify, read
            // Gradle's reference documentation.
            all {
                // Sets JVM argument(s) for the test JVM(s).
                jvmArgs = listOf("-XX:MaxPermSize=256m")

                // You can also check the task name to apply options to only the
                // tests you specify.
                if (it.name == "testDebugUnitTest") {
                    systemProperty = mapOf("debug" to "true")
                }
                ...
            }
        }
    }
}

对插桩测试使用单独的测试模块

如果您希望某个模块专用于插桩测试并将代码的其余部分与测试隔离,您可以创建一个单独的测试模块并配置其 build,创建和配置方式与库模块类似。如需创建测试模块,请按以下步骤操作:

  1. 创建一个库模块
  2. 在模块级 build 文件 build.gradle 中,应用 com.android.test 插件(而非 com.android.library)。
  3. 点击 Sync Project 以同步您的项目

创建测试模块后,您可以在主源代码集或变体源代码集(例如 src/main/javasrc/variant/java)内添加您的测试代码。如果您的应用模块定义了多个产品变种,您可以在测试模块中重新创建这些变种,并且测试模块会使用变体感知依赖项管理功能尝试测试目标模块中的匹配变种。

默认情况下,测试模块仅包含并测试 debug 变体。不过,您可以创建新的 build 类型,使其与测试的应用项目匹配。如需让测试模块对其他 build 类型(而非调试 build 类型)进行测试,请使用 VariantFilter 停用测试项目中的 debug 变体,如下所示:

Groovy

android {
    variantFilter { variant ->
        if (variant.buildType.name.equals('debug')) {
            variant.setIgnore(true);
        }
    }
}

Kotlin

android {
    variantFilter {
        if (buildType.name == "debug") {
            ignore = true
        }
    }
}

如果您希望测试模块仅对应用的某些变种或 build 类型进行测试,则可以使用 matchingFallbacks 属性来限制要测试哪些变体。这也使得测试模块无需针对自身配置这些变体。