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

入门

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

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

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

虽然测试应该在生成报告之前执行,但 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.11"
    reportsDirectory = layout.buildDirectory.dir("customJacocoReportDir")
}
build.gradle
jacoco {
    toolVersion = "0.8.11"
    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
            }
        }
    }
}

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

JaCoCo 特定任务配置

JaCoCo 插件将 JacocoTaskExtension 扩展添加到所有类型为 Test 的任务。此扩展允许配置测试任务的 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 代理运行而配置的任务会在任务开始执行时删除执行数据的目标文件。这确保了执行数据中不存在过时的覆盖率数据。

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 插件增强。也就是说,任何分叉 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 代理库。

输出变体

当与 JVM 测试套件插件 一起应用生成 JaCoCo 覆盖率数据的项目时,将创建额外的输出变体。这些变体旨在供 JaCoCo 报告聚合插件 使用。

属性将类似于以下内容。用户可配置的属性在示例下方突出显示。

outgoingVariants 任务输出
--------------------------------------------------
Variant coverageDataElementsForTest (i)
--------------------------------------------------
Description = Binary data file containing results of Jacoco test coverage reporting for the test Test Suite's test target.

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

Artifacts
    - build/jacoco/test.exec (artifactType = binary)
1 TestSuiteName 属性;值来自 JvmTestSuite#getName()
2 TestSuiteTargetName 属性;值来自 JvmTestSuiteTarget#getName()
3 TestSuiteType 属性;值来自 JvmTestSuite#getTestType()