JaCoCo 插件通过与 JaCoCo 集成为 Java 代码提供代码覆盖率指标。

入门

要开始使用,请将 JaCoCo 插件应用于您要计算代码覆盖率的项目。

build.gradle.kts
plugins {
    jacoco
}
build.gradle
plugins {
    id 'jacoco'
}

如果您的项目也应用了 Java 插件,则会创建一个名为 jacocoTestReport 的新任务。默认情况下,会在 layout.buildDirectory.dir("reports/jacoco/test") 生成一个 HTML 报告。

虽然应在生成报告之前执行测试,但 jacocoTestReport 任务不依赖于 test 任务。

根据您的用例,您可能希望始终生成 jacocoTestReport,或者在明确生成报告之前运行 test 任务。

build.gradle.kts
tasks.test {
    finalizedBy(tasks.jacocoTestReport) // report is always generated after tests run
}
tasks.jacocoTestReport {
    dependsOn(tasks.test) // tests are required to run before generating the report
}
build.gradle
test {
    finalizedBy jacocoTestReport // report is always generated after tests run
}
jacocoTestReport {
    dependsOn test // tests are required to run before generating the report
}

配置 JaCoCo 插件

JaCoCo 插件会添加一个名为 jacoco 的项目扩展,类型为 JacocoPluginExtension,它允许您配置构建中使用 JaCoCo 的默认设置。

build.gradle.kts
jacoco {
    toolVersion = "0.8.13"
    reportsDirectory = layout.buildDirectory.dir("customJacocoReportDir")
}
build.gradle
jacoco {
    toolVersion = "0.8.13"
    reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir')
}
表 1. JaCoCo 属性的 Gradle 默认值
属性 Gradle 默认值

reportsDirectory

layout.buildDirectory.dir("reports/jacoco")

JaCoCo 报告配置

JacocoReport 任务可用于生成不同格式的代码覆盖率报告。它实现了标准的 Gradle 类型 Reporting,并暴露了类型为 JacocoReportsContainer 的报告容器。

build.gradle.kts
tasks.jacocoTestReport {
    reports {
        xml.required = false
        csv.required = false
        html.outputLocation = layout.buildDirectory.dir("jacocoHtml")
    }
}
build.gradle
jacocoTestReport {
    reports {
        xml.required = false
        csv.required = false
        html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
    }
}
JaCoCo HTML report

强制执行代码覆盖率指标

此功能需要使用 JaCoCo 0.6.3 或更高版本。

JacocoCoverageVerification 任务可用于根据配置的规则验证代码覆盖率指标是否达标。其 API 暴露了方法 JacocoCoverageVerification.violationRules(org.gradle.api.Action),此方法是配置规则的主要入口点。调用这些方法中的任何一个都将返回 JacocoViolationRulesContainer 的实例,提供丰富的配置选项。如果任何配置的规则未达标,构建将失败。JaCoCo 只报告第一个违规规则。

代码覆盖率要求可以针对整个项目、单个文件以及特定的 JaCoCo 覆盖类型(例如,行覆盖率或分支覆盖率)进行指定。以下示例描述了语法。

build.gradle.kts
tasks.jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = "0.5".toBigDecimal()
            }
        }

        rule {
            isEnabled = false
            element = "CLASS"
            includes = listOf("org.gradle.*")

            limit {
                counter = "LINE"
                value = "TOTALCOUNT"
                maximum = "0.3".toBigDecimal()
            }
        }
    }
}
build.gradle
jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = 0.5
            }
        }

        rule {
            enabled = false
            element = 'CLASS'
            includes = ['org.gradle.*']

            limit {
                counter = 'LINE'
                value = 'TOTALCOUNT'
                maximum = 0.3
            }
        }
    }
}

JacocoCoverageVerification 任务不是 Java 插件提供的 check 任务的任务依赖项。这有充分的理由。该任务目前不是增量的,因为它没有声明任何输出。在执行 check 任务时,任何违反声明规则的行为都会自动导致构建失败。对于所有用户来说,这种行为可能并非期望的。Gradle 的未来版本可能会改变此行为。

JaCoCo 特有任务配置

JaCoCo 插件会向所有类型为 Test 的任务添加一个 JacocoTaskExtension 扩展。此扩展允许配置测试任务的 JaCoCo 特有属性。

build.gradle.kts
tasks.test {
    extensions.configure(JacocoTaskExtension::class) {
        destinationFile = layout.buildDirectory.file("jacoco/jacocoTest.exec").get().asFile
        classDumpDir = layout.buildDirectory.dir("jacoco/classpathdumps").get().asFile
    }
}
build.gradle
test {
    jacoco {
        destinationFile = layout.buildDirectory.file('jacoco/jacocoTest.exec').get().asFile
        classDumpDir = layout.buildDirectory.dir('jacoco/classpathdumps').get().asFile
    }
}

配置为使用 JaCoCo agent 运行的任务会在任务开始执行时删除执行数据的目标文件。这确保了执行数据中没有陈旧的覆盖率数据。

JaCoCo 任务扩展的默认值

build.gradle.kts
tasks.test {
    configure<JacocoTaskExtension> {
        isEnabled = true
        destinationFile = layout.buildDirectory.file("jacoco/${name}.exec").get().asFile
        includes = emptyList()
        excludes = emptyList()
        excludeClassLoaders = emptyList()
        isIncludeNoLocationClasses = false
        sessionId = "<auto-generated value>"
        isDumpOnExit = true
        classDumpDir = null
        output = JacocoTaskExtension.Output.FILE
        address = "localhost"
        port = 6300
        isJmx = false
    }
}
build.gradle
test {
    jacoco {
        enabled = true
        destinationFile = layout.buildDirectory.file("jacoco/${name}.exec").get().asFile
        includes = []
        excludes = []
        excludeClassLoaders = []
        includeNoLocationClasses = false
        sessionId = "<auto-generated value>"
        dumpOnExit = true
        classDumpDir = null
        output = JacocoTaskExtension.Output.FILE
        address = "localhost"
        port = 6300
        jmx = false
    }
}

虽然所有类型为 Test 的任务在应用 java 插件后会自动增强以提供覆盖率信息,但任何实现 JavaForkOptions 的任务都可以被 JaCoCo 插件增强。也就是说,任何 fork Java 进程的任务都可以用于生成覆盖率信息。

例如,您可以配置您的构建以使用 application 插件生成代码覆盖率。

build.gradle.kts
plugins {
    application
    jacoco
}

application {
    mainClass = "org.gradle.MyMain"
}

jacoco {
    applyTo(tasks.run.get())
}

tasks.register<JacocoReport>("applicationCodeCoverageReport") {
    executionData(tasks.run.get())
    sourceSets(sourceSets.main.get())
}
build.gradle
plugins {
    id 'application'
    id 'jacoco'
}

application {
    mainClass = 'org.gradle.MyMain'
}

jacoco {
    applyTo run
}

tasks.register('applicationCodeCoverageReport', JacocoReport) {
    executionData run
    sourceSets sourceSets.main
}
由 applicationCodeCoverageReport 生成的覆盖率报告
.
└── build
    ├── jacoco
    │   └── run.exec
    └── reports
        └── jacoco
            └── applicationCodeCoverageReport
                └── html
                    └── index.html

任务

对于同时应用了 Java 插件的项目,JaCoCo 插件会自动添加以下任务:

jacocoTestReportJacocoReport

为测试任务生成代码覆盖率报告。

jacocoTestCoverageVerificationJacocoCoverageVerification

根据为测试任务指定的规则验证代码覆盖率指标。

依赖管理

JaCoCo 插件添加了以下依赖配置:

表 2. JaCoCo 插件 - 依赖配置
名称 含义

jacocoAnt

用于运行 JacocoReportJacocoCoverageVerification 任务的 JaCoCo Ant 库。

jacocoAgent

用于对被测代码进行插桩的 JaCoCo agent 库。

输出变体

当一个产生 JaCoCo 覆盖率数据的项目与 JVM Test Suite Plugin 一起应用时,将创建额外的输出变体。这些变体专为 JaCoCo Report Aggregation Plugin 消费而设计。

属性将如下所示。用户可配置的属性在示例下方突出显示。

outgoingVariants 任务输出
--------------------------------------------------
Variant coverageDataElementsForTest (i)
--------------------------------------------------
Binary results containing Jacoco test coverage for all targets in the 'test' Test Suite.

Capabilities
    - org.gradle.sample:application:1.0.2 (default capability)
Attributes
    - org.gradle.category         = verification
    - org.gradle.testsuite.name   = test           (1)
    - org.gradle.verificationtype = jacoco-coverage

Artifacts
    - build/jacoco/test.exec (artifactType = binary)
1 TestSuiteName 属性;其值来源于 TestSuite#getName()