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

Android Studio多模块项目无法生成Jacoco报告问题排查

环境信息

  • JDK版本:11
  • Gradle版本:7.5
  • Jacoco版本:0.8.8

问题场景

编写聚合多模块单元测试覆盖率报告的jacocoTotalReport任务时遇到两个问题:

  1. 加入doFirst代码块动态收集子模块执行数据时,触发错误:

    The value for this file collection is final and cannot be changed.
    对应代码:

    task jacocoTotalReport(type: JacocoReport, dependsOn: project.getTasksByName("testDebugUnitTest", true)) {
        doFirst {
            subprojects.each { project ->
               
                def unitTestResultFile = "${project.buildDir}/jacoco/testDebugUnitTest.exec"
    
                if (file(unitTestResultFile).exists() && executionData != null) {
                    executionData.setFrom(unitTestResultFile)
                }
            }
        }
    }
    
  2. 移除doFirst后执行无报错,但无法生成覆盖率报告,对应代码:
    task jacocoTotalReport(type: JacocoReport, dependsOn: project.getTasksByName("testDebugUnitTest", true)) {
     
            subprojects.each { project ->
    
                def unitTestResultFile = "${project.buildDir}/jacoco/testDebugUnitTest.exec"
    
                if (file(unitTestResultFile).exists() && executionData != null) {
                    executionData.setFrom(unitTestResultFile)
                }
            }
        
    }
    

问题原因

  1. doFirst报错原因:Gradle任务执行阶段(doFirst/doLast的执行时机),JacocoReport的executionData文件集合已被固化为不可变状态,此时调用setFrom修改会触发文件集合不可变的错误。
  2. 移除doFirst无报告原因:配置阶段遍历子模块时,testDebugUnitTest任务还未执行,对应的exec文件尚未生成,file(...).exists()判断为false,导致没有任何执行数据被添加到任务中,自然无法生成报告。

解决方案

利用Gradle延迟配置特性,让框架自动处理文件存在性判断和任务依赖,同时补充生成报告必需的源码、类文件路径配置:

task jacocoTotalReport(type: JacocoReport) {
    // 依赖所有子模块的debug单元测试任务,确保测试先执行
    dependsOn subprojects.testDebugUnitTest

    // 延迟收集子模块的exec文件,Gradle会在任务执行前解析实际路径
    executionData subprojects.files { project ->
        "${project.buildDir}/jacoco/testDebugUnitTest.exec"
    }

    // 指定所有子模块的源码路径,用于映射覆盖率数据
    sourceDirectories.from subprojects.sourceSets.main.java.srcDirs
    // 指定所有子模块的编译类文件路径
    classDirectories.from subprojects.sourceSets.main.output

    // 配置报告输出格式和路径(可按需调整)
    reports {
        html.required = true
        xml.required = true
        csv.required = false
        html.outputLocation = layout.buildDirectory.dir("reports/jacoco/total/html")
    }
}

关键说明

  • 用subprojects.files { ... }声明executionData属于延迟配置,会在任务执行前才解析文件路径,此时测试任务已完成,exec文件已存在,无需手动判断。
  • 必须配置sourceDirectories和classDirectories,否则Jacoco无法将执行数据映射到源码,无法生成有效报告。
  • 直接依赖subprojects.testDebugUnitTest比getTasksByName更简洁,确保所有子模块测试任务优先执行。

内容的提问来源于stack exchange,提问作者Dehong Liang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 12:05:11