Gradle如何检测指定目录下是否存在带@Test注解的有效测试方法
Gradle 检测Android项目Instrumentation测试的实现方案
你原有实现存在路径硬编码、判断逻辑粗糙两个核心问题,以下提供两种可直接落地的实现,可根据调用场景选择:
方案1:轻量文件扫描版(配置阶段可用,性能优先)
该方案不需要等待全项目配置完成,执行速度快,兼容自定义源码路径配置,满足绝大多数场景需求:
def doesProjectContainsInstrumentationTests(Project project) { // 非Android项目直接返回false,无Instrumentation测试可能 def isAndroidProject = project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library") || project.plugins.hasPlugin("com.android.dynamic-feature") if (!isAndroidProject) { return false } // 直接从AGP取androidTest源集配置,兼容自定义源码路径 def androidTestSourceSet = project.android.sourceSets.findByName("androidTest") if (androidTestSourceSet == null) { return false } // 递归遍历所有androidTest源码目录,检测是否存在测试类 return androidTestSourceSet.java.srcDirs.any { srcDir -> if (!srcDir.exists() || !srcDir.isDirectory()) { return false } // 扫描所有java/kt文件,匹配测试类特征 return project.fileTree(srcDir) { include "**/*.java", "**/*.kt" }.any { testFile -> def content = testFile.text // 兼容JUnit4注解、Kotlin注解写法、JUnit3继承写法 return content.contains("@Test") || content.contains("@RunWith") || content.contains("@get:Test") || (content.contains("extends TestCase") && content.contains("void test")) } } }
方案特点
- 不需要等AGP配置完成,可在配置阶段直接调用
- 自动适配项目自定义的androidTest源码目录,不会因为修改sourceSets配置失效
- 空目录、目录下仅包含清单文件/资源文件/非测试工具类的场景会正确返回false
方案2:AGP逻辑对齐版(配置完成后调用,准确率优先)
如果需要100%和Android Gradle插件的官方检测逻辑对齐,避免自定义扫描规则的漏判误判,可以在项目配置完成后通过编译产物判断,该方案完全复用AGP的测试识别逻辑,支持所有测试框架(Espresso、Compose Test、JUnit4/5等):
// 注意:该方法必须在afterEvaluate回调内调用,否则会因AGP未完成变体配置报错 def doesProjectContainsInstrumentationTests(Project project) { def isAndroidProject = project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library") if (!isAndroidProject) { return false } def hasValidTests = false // 遍历所有构建变体的androidTest编译产物 project.android.testVariants.all { variant -> def compiledTestClasses = variant.javaCompileProvider.get().destinationDirectory // 检测是否存在编译后的测试类字节码 if (project.fileTree(compiledTestClasses) { include "**/*Test.class", "**/*Tests.class" }.files.size() > 0) { hasValidTests = true } } return hasValidTests }
调用示例
project.afterEvaluate { if (doesProjectContainsInstrumentationTests(project)) { // 执行依赖Instrumentation测试的逻辑,比如创建测试任务、配置测试流水线参数等 } }
方案特点
- 准确率最高,和AGP执行测试时的判断逻辑完全一致
- 不需要自定义测试特征匹配规则,新的测试框架版本也能兼容
- 仅适合在配置完成后调用,不适合配置早期需要拿结果的场景
原有实现的问题说明
- 手动拼接项目路径的逻辑不兼容自定义projectDir、自定义源码目录的项目,容易出现路径判断错误
- 仅判断文件夹存在的逻辑无法过滤空目录、无测试代码的目录,误判率高
- 没有做Android插件校验,纯Java/Kotlin子项目会被误判为存在Instrumentation测试
内容的提问来源于stack exchange,提问作者amp
相关产品推荐
相关产品推荐

