4 测试(Testing)
构建一个测试应用已集成在应用项目中,不再需要单独的测试项目。
4.1 单元测试(Unit testing)
单元测试在1.1版本中添加支持,请查看其他页面了解详情。其他部分描述了可运行在真实设备或模拟器上,并且需要构建一个单独的测试APK的“instrumentation tests”。
4.2 基础及配置(Basics and Configuration)
正如前面所提到的,位于main构建类型(Build Type)旁边的是androidTest构建类型(Build Type),默认位置位于src/androidTest/。使用这个源码集合(sourceSets),会构建一个使用Android测试框架,并且可以部署到设备上来测试应用的测试APK。其中包含android单元测试、集成测试及UI自动化测试。测试应用的清单(manifest)节点<instrumentation>
是自动生成的,但你可以创建一个src/androidTest/AndroidManifest.xml文件去添加其他组件到测试清单(manifest)中。
对于测试应用,存在着一些可以进行配置的值,主要作用于<instrumentation>
节点:
- testApplicationId
- testInstrumentationRunner
- testHandleProfiling
- testFunctionalTest
正如前面看到的,这些配置位于defaultConfig对象中:
android {
defaultConfig {
testPackageName "com.test.foo"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
testHandleProfiling true
testFunctionalTest true
}
}
在测试应用清单(manifest)文件中,instrumentation节点的targetPackage属性会自动替换为测试应用的包名,即使包名已通过defaultConfig
或者构建类型(Build Type)进行自定义也不例外。这是清单(manifest)的这个部分是自动生成的一个原因。
另外,androidTest源码集合(source set)可以配置自己的依赖关系。默认情况下,应用及其依赖关系会被添加到测试应用的类路径(classpath)中,但可以通过以下代码片段进行扩展:
dependencies {
androidTestCompile 'com.google.guava:guava:11.0.2'
}
测试应用通过assembleAndroidTest任务来构建。该任务不依赖于assemble任务,而是当测试运行时自动调用。
目前只能测试一个构建类型(Build Type),默认是测试debug构建类型(Build Type),但是可以重新配置:
andorid {
...
testBuildType "staging"
}
4.3 解决主APK与测试APK的冲突(Resolving conflicts between main and test APK)
当测试用例运行时,主APK与测试APK使用相同的类路径(classpath),如果主APK与测试APK使用相同的库但版本不一致,会导致Gradle构建错误。如果Gradle不能获取到该错误,你的应用在测试中和正常运行中的表现会不一致(包括在某种情况下导致的崩溃错误)。
为了确保构建成功,只需要保证两个APK使用相同的版本即可。如果错误是关于一个间接依赖(未在build.gradle中直接提及的库),只需要在所需配置中添加最新版本的依赖关系("compile"或"androidTestCompile"),当然你也可以使用Gradle的解决策略机制。你可以通过运行./gradlew :app:dependencies
和./gradlew :app:androidDependencies
来检查依赖关系树。
4.4 运行测试(Running tests)
正如前面所提到的,检查操作需要一个通过锚任务connectedCheck来启动的已连接设备,其依赖于connectedDebugAndroidTest任务,并且因此运行connectedDebugAndroidTest任务。该任务做如下操作:
- 确认应用及测试应用已构建(依赖于assembleDebug和assembleDebugAndroidTest)
- 安装两个应用
- 运行测试
- 卸载两个应用
如果有多个设备连接,所有测试会在所有已连接设备上并行运行。如果一个测试失败,则在所有设备上都算失败。
4.5 测试Android库(Testing Android Libraries)
测试Android库项目与应用项目是完全相同的方式。唯一的不同是整个库(及其依赖关系)自动作为一个依赖库添加到测试应用中。使得测试APK不仅包含自己的代码,也包括库及其所有依赖关系。库的清单(manifest)文件合并到测试应用的清单(manifest)文件中(与引用该库的其他项目情况相同)。androidTest任务的差别是只安装(或卸载)测试APK(因为没有其他APK可安装),其他方面则是相同的。
4.6 测试报告(Test reports)
当运行单元测试时,Gradle输出一份HTML报告用以方便查看测试结果,Android插件在其HTML报告基础上扩展,来集成所有连接设备的测试结果。所有测试结果作为XML文件保存在build/reports/androidTests/目录下(与常规的JUnit结果保存在build/reports/tests/类似)。该路径可进行配置:
android {
...
testOptions {
resultsDir = "${project.buildDir}/foo/results"
}
}
android.testOptions.resultsDir
的值可参考Project.file(String))
4.6.1 多项目报告(Multi-projects reports)
在一个有多个应用项目及多个库项目的多项目配置中,当同时运行所有测试时,对所有测试结果只生成一份报告是非常有用的。
要做到这一点,可以使用同一个工件(artifact)下的另一个插件:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'
}
}
apply plugin: 'android-reporting'
这代码应该添加到根项目,与settings.gradle文件同目录下的build.gradle文件中
然后在根目录下,使用以下命令运行所有测试并合成所有报告:
gradle deviceCheck mergeAndroidReports --continue
注意:--continue
确保所有的子项目测试都会运行,即使其中一个运行失败也不会终止。如果没有该选项,则第一个失败的测试会中断运行,而不是继续运行所有测试。
4.7 Lint报告(Lint support)
你可以为一个特定的变种(variant)运行lint,例如:./gradlew lintRelease
,或者为所有变种(variant)运行lint。在这种情况下,它会生成一个报告来描述哪个指定的变种(variant)存在问题。你可以通过添加lintOptions来配置lint。你通常只会使用到其中一小部分配置,可以查看DSL引用获取所有可以选项。
android {
lintOptions {
// turn off checking the given issue id's
disable 'TypographyFractions','TypographyQuotes'
// turn on the given issue id's
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// check *only* the given issue id's
check 'NewApi', 'InlinedApi'
}
}