Gradle执行阶段设置Test Instrumentation Runner参数无效问题排查
关于Gradle执行阶段动态设置测试参数的问题
你遇到的核心问题是:没办法在Gradle执行阶段动态修改testInstrumentationRunnerArguments来过滤测试,这是因为Android Gradle插件的测试任务(比如connectedAndroidTest这类)在配置阶段就已经把测试参数绑定到了任务的执行命令里,执行阶段再修改android.productFlavors里的参数只是改变了内存中的对象属性,根本不会同步到已经生成好的任务命令行参数中,所以测试过滤完全不生效。
具体原因拆解
Android Gradle插件在配置阶段会为每个connectedAndroidTest任务生成对应的am instrument命令,其中的-e参数就是从testInstrumentationRunnerArguments里读取的。等进入执行阶段时,任务的执行命令已经固定了,你再修改testInstrumentationRunnerArguments的内容,插件不会重新生成命令,自然也就不会生效。你提到的相关Bug记录也印证了这一点——旧版本的Android插件(比如你用的3.0.1)确实存在这个限制,执行阶段的参数修改无法同步到测试任务。
可行的解决方案
既然执行阶段走不通,我们可以把参数配置逻辑移到配置阶段,通过项目属性(比如-P参数)来动态控制测试过滤规则。下面是针对你的脚本修改后的方案:
1. 调整参数配置逻辑到配置阶段
把原来在doFirst里的参数设置逻辑,改成在配置阶段根据项目属性来处理:
ext { integrationTest = project.hasProperty('integrationTest') networkIntegrationTest = project.hasProperty('networkIntegrationTest') } android.sourceSets { androidTest { java { srcDirs += './src/integrationNetworkTest/java' srcDirs += './src/integrationTest/java' } res { srcDirs += './src/integrationNetworkTest/res' srcDirs += './src/integrationTest/res' } } } // 在配置阶段处理测试参数 android.productFlavors.each { flavor -> def annotationList = [] if (integrationTest) { annotationList.add('com.company.android.infrastructure.test.IntegrationTest') } if (networkIntegrationTest) { annotationList.add('com.company.android.infrastructure.test.IntegrationNetworkTest') } if (annotationList.isEmpty()) { // 默认排除两个注解的测试 flavor.testInstrumentationRunnerArguments.notAnnotation = 'com.company.android.infrastructure.test.IntegrationTest,com.company.android.infrastructure.test.IntegrationNetworkTest' } else { // 根据属性只运行指定注解的测试 flavor.testInstrumentationRunnerArguments.annotation = annotationList.join(',') } }
2. 修改自定义测试任务
原来的自定义任务用doLast设置变量的方式行不通,改成直接触发带项目属性的测试任务:
project.afterEvaluate { android.libraryVariants.each { variant -> tasks.create("${variant.name}IntegrationTest") { group 'company' description 'Run company Integration tests with only network requests mocked' doLast { // 调用对应的测试任务并传递integrationTest属性 exec { def gradleCmd = "${gradle.gradleHomeDir}/bin/gradle" if (System.getProperty('os.name').toLowerCase().contains('windows')) { gradleCmd += '.bat' } commandLine gradleCmd, ":connected${variant.name.capitalize()}AndroidTest", '-PintegrationTest=true' } } } tasks.create("${variant.name}IntegrationNetworkTest") { group 'company' description 'Run company Integration tests with real network requests' doLast { exec { def gradleCmd = "${gradle.gradleHomeDir}/bin/gradle" if (System.getProperty('os.name').toLowerCase().contains('windows')) { gradleCmd += '.bat' } commandLine gradleCmd, ":connected${variant.name.capitalize()}AndroidTest", '-PnetworkIntegrationTest=true' } } } } }
这样修改后的效果
- 运行
./gradlew appDebugIntegrationTest时,会自动触发connectedDebugAndroidTest并带上-PintegrationTest=true属性,配置阶段会读取这个属性设置对应的annotation参数,只运行标记了IntegrationTest注解的测试 - 运行
./gradlew appDebugIntegrationNetworkTest则会只运行IntegrationNetworkTest注解的测试 - 直接运行
connectedDebugAndroidTest时,会默认排除这两个注解的测试,和你原来的逻辑一致
内容的提问来源于stack exchange,提问作者JTT
相关产品推荐
相关产品推荐

