如何从带有 Gradle 的 JaCoCo 测试报告中排除隐式 Groovy 闭包 类

How do you exclude implicit Groovy closure classes from JaCoCo test resport with Gradle

如果您在 Groovy 项目上使用 JaCoCo,您会在覆盖率报告中得到很多隐式创建的闭包 类。链接到这些的来源是封闭的 类。封闭 类 的覆盖率报告也包含闭包覆盖率,因此它不会为覆盖率报告增加任何值。更糟糕的是,它伪造了覆盖率报告,因为要覆盖在闭包中的语句在整体统计中被计算了两次。

那么如何从生成的 JaCoCo 覆盖率报告中排除这些闭包?

您可以使用以下代码片段从 JaCoCo 记录中排除隐式闭包 classes,这不会阻止语句被记录在封闭的 class

test {
    jacoco.excludes = ['**/*$*_closure*']
}

有了这个片段,覆盖率不再被记录,但现在所有关闭在报告中显示为 0% 覆盖率,因此也减少了总体覆盖率统计数据。

添加以下代码段将从 JaCoCo 报告中删除闭包 classes,因此也会提供更有意义的总体统计数据。上面的代码片段并不是必需的,它只是带来了一点性能提升,因为不需要为报告记录和转换覆盖率,所以我建议同时使用这两个代码片段。

jacocoTestReport {
    doFirst {
        classDirectories = classDirectories.collect { fileTree(it) { exclude '**/*$*_closure*' } }.sum()
    }
}

如果您有多个 TestJacocoReport 任务要以这种方式修改,您当然也可以像

tasks.withType(Test) {
    jacoco.excludes = ['**/*$*_closure*']
}

tasks.withType(JacocoReport) {
    doFirst {
        classDirectories = classDirectories.collect { fileTree(it) { exclude '**/*$*_closure*' } }.sum()
    }
}

不适用于 Gradle 6.6.1。此代码片段可以完成工作:

tasks.withType(Test) {
    jacoco.excludes = ['**/*$*_closure*']
    finalizedBy jacocoTestReport // report is always generated after tests run
}

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, excludes: ['**/*$*_closure*'])
        }))
    }

    dependsOn test // tests are required to run before generating the report
}