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

多模块Android项目集成测试代码覆盖率报告生成求助

跨模块Android集成测试覆盖率报告解决方案

针对所有集成测试集中在app模块androidTest目录、需要覆盖其他feature模块和Java工具模块的场景,可通过以下步骤实现全模块覆盖率收集与合并:

1. 为所有被测试模块启用覆盖率收集

默认只有测试代码所在的app模块会生成覆盖率数据,因此需要为其他模块开启覆盖率 instrumentation:

Android功能模块(feature-module1、feature-module2)

在每个模块的build.gradle中添加:

android {
    buildTypes {
        debug {
            testCoverageEnabled true
        }
    }
}

Java工具模块(util-module)

纯Java库需配置Jacoco支持:

jacoco {
    toolVersion = "0.8.11" // 使用最新稳定版本
}

tasks.withType(Test) {
    jacoco.includeNoLocationClasses = true
}

2. 配置app模块收集跨模块覆盖率数据

修改app模块的build.gradle,指定覆盖率文件输出路径,并添加任务拉取、合并所有模块的覆盖率数据:

android {
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        // 强制将覆盖率数据输出到设备统一路径,方便后续拉取
        testInstrumentationRunnerArguments += ["coverageFile": "/sdcard/coverage.ec"]
    }
}

// 从设备拉取生成的覆盖率文件到本地
task pullCoverageReport(type: Exec) {
    dependsOn 'connectedDebugAndroidTest'
    commandLine 'adb', 'pull', '/sdcard/coverage.ec', "$buildDir/outputs/coverage/merged-coverage.ec"
}

// 生成合并后的全模块覆盖率报告
task generateMergedCoverageReport(type: JacocoReport) {
    dependsOn pullCoverageReport
    group = "Reporting"
    description = "生成包含所有模块的Jacoco覆盖率报告"

    // 配置所有模块的class文件路径(排除无需统计的类)
    def appClasses = fileTree(dir: "$project(':app').buildDir/intermediates/classes/debug", 
        excludes: ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*'])
    def feature1Classes = fileTree(dir: "$project(':feature-module1').buildDir/intermediates/classes/debug", 
        excludes: ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*'])
    def feature2Classes = fileTree(dir: "$project(':feature-module2').buildDir/intermediates/classes/debug", 
        excludes: ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*'])
    def utilClasses = fileTree(dir: "$project(':util-module').buildDir/classes/java/main", 
        excludes: ['**/BuildConfig.*'])

    // 指定所有模块的源码路径
    sourceDirectories.from = files(
        project(':app').sourceSets.main.java.srcDirs,
        project(':feature-module1').sourceSets.main.java.srcDirs,
        project(':feature-module2').sourceSets.main.java.srcDirs,
        project(':util-module').sourceSets.main.java.srcDirs
    )
    // 指定所有模块的class文件
    classDirectories.from = files(appClasses, feature1Classes, feature2Classes, utilClasses)
    // 指定拉取到的合并覆盖率数据文件
    executionData.from = file("$buildDir/outputs/coverage/merged-coverage.ec")

    // 配置报告输出格式
    reports {
        html.enabled = true // HTML报告(最直观)
        xml.enabled = true // XML报告(用于CI工具)
        csv.enabled = false // 可根据需求开启
    }
}

3. 生成完整覆盖率报告

在终端执行以下命令:

./gradlew generateMergedCoverageReport

该命令会自动完成:运行所有集成测试 → 从设备拉取覆盖率文件 → 合并所有模块的源码与class数据 → 生成完整的覆盖率报告。报告默认输出在app/build/reports/jacoco/generateMergedCoverageReport/html目录下,打开index.html即可查看全模块覆盖率详情。

常见问题排查

  • 部分模块覆盖率未统计:检查对应模块是否开启了testCoverageEnabled(Android模块)或Jacoco配置(Java模块);若为Kotlin模块,class文件路径需改为buildDir/intermediates/classes/kotlin/debug。
  • 覆盖率文件拉取失败:手动执行adb shell ls /sdcard/coverage.ec确认文件存在,若不存在需检查testInstrumentationRunnerArguments配置是否正确,或设备是否有写入权限(可临时关闭设备的存储权限限制)。
  • 无覆盖率数据:确保集成测试确实执行了对应模块的代码,未被测试覆盖的代码不会出现在报告中。

内容的提问来源于stack exchange,提问作者Rich Luick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:11:16