You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 18:54:32