使用 Gradle 过滤 JaCoCo 覆盖率报告
Filter JaCoCo coverage reports with Gradle
问题:
我有一个包含 jacoco 的项目,我希望能够过滤某些 类 and/or 包。
相关文档:
我已阅读以下文档:
官方jacoco网站:
http://www.eclemma.org/jacoco/index.html
gradle的官方 jacoco 文档: https://gradle.org/docs/current/userguide/jacoco_plugin.html
官方 jacoco Github
问题,正在处理报道:
https://github.com/jacoco/jacoco/wiki/FilteringOptions
https://github.com/jacoco/jacoco/issues/14
相关 Whosebug 链接:
JaCoCo & Gradle - Filtering Options(无人回答)
Exclude packages from Jacoco report using Sonarrunner and Gradle (Not using sonar)
JaCoCo - exclude JSP from report (It seems to work for maven, I am using gradle)
(It seems to work for maven, I am using gradle)
JaCoCo gradle plugin exclude(无法正常工作)
Gradle Jacoco - coverage reports includes classes excluded in configuration(看起来很接近,用了doFirst
,对我没用)
我尝试过的示例:
apply plugin: 'java'
apply plugin: 'jacoco'
buildscript {
repositories {
mavenCentral()
jcenter()
}
}
repositories {
jcenter()
}
jacocoTestReport {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
test {
jacoco {
destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
classDumpFile = file("$buildDir/jacoco/classpathdumps")
excludes = ["projecteuler/**"] // <-- does not work
// excludes = ["projecteuler"]
}
}
}
问题:
如何在生成 jacoco 覆盖率报告时排除某些包和 类?
感谢,Yannick Welsch
:
在搜索 Google、阅读 Gradle 文档并浏览旧的 Whosebug 帖子后,我在官方 gradle 论坛上找到了这个答案!
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/blah/**')
}))
}
}
来源: https://issues.gradle.org/browse/GRADLE-2955
对于较早的 gradle 版本 < 5.x 可能需要使用
classDirectories = files(classDirectories.files.collect {
而不是 classDirectories.setFrom
我的 build.gradle
项目 Java/Groovy 的解决方案:
apply plugin: 'java'
apply plugin: 'jacoco'
jacocoTestReport {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**'])
})
}
}
如您所见,我成功地向 exclude:
添加了更多内容以过滤一些包。
来源: https://github.com/jaredsburrows/CS-Interview-Questions/blob/master/build.gradle
其他项目的自定义任务,例如 Android:
apply plugin: 'jacoco'
task jacocoReport(type: JacocoReport) {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**'])
})
}
}
Here 是 ANT 中针对此问题的解决方案。这可以通过在 jacocoTestReport
任务下添加以下内容来适应 gradle。尽管 jacoco 并未真正记录这一点,但它似乎是目前过滤测试结果的唯一方法。
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'excluded/files/**')
})
}
这已经有一段时间了,但我只是 运行 了解了这一点。我正在为所有需要的排除而苦苦挣扎。我发现这对我来说要简单得多。如果你遵循 Maven 项目布局风格 /src/main/java 和 /src/test/java,你只需要把 buildDir/classes/main 在你的 classDirectories 配置中像这样:
afterEvaluate {
jacocoTestReport {
def coverageSourceDirs = ['src/main/java']
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/reports/jacocoHtml"
}
sourceDirectories = files(coverageSourceDirs)
classDirectories = fileTree(
dir: "${project.buildDir}/classes/main",
excludes: [
//whatever here like JavaConfig etc. in /src/main/java
]
)
}
}
对我来说,与
一起工作很好
test {
jacoco {
excludes += ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**']
}
}
如文档中所述
https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 最初被问到
所以答案是:
所以如果你问我:这不是
的问题
excludes = ["projecteuler/**"]
或
excludes += ["projecteuler/**"]
但是
excludes = ["**/projecteuler/**"]
排除包*.projecteuler.*
和 test {}
在项目级别,未嵌套在 jacocoTestReport
中
下面的代码也将 类 排除在覆盖验证之外:
jacocoTestCoverageVerification {
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: "${project.buildDir}/classes/main",
exclude: ['**/packagename/**'])
})
}
}
对于 Gradle 版本 5.x,classDirectories = files(...)
给出弃用警告并且从 Gradle 6.0 开始根本不起作用
这是不推荐使用的排除 类:
的方式
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/exclude/**')
}))
}
}
在 gradle.properties 文件中添加以下配置
coverageExcludeClasses=["com.example.package.elasticsearch.*", "com.example.package2.*",]
一些评论提到了弃用警告。解决只需使用 getter:
afterEvaluate {
getClassDirectories().from(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/blah/**')
}))
}
对于Gradle6
使用类似下面的东西,因为他们制作了 classDirectories as final
,我们无法重新分配它,但是存在 setter 方法 classDirectories.setFrom
可以利用
jacocoTestReport {
reports {
xml.enabled true
html.enabled true
html.destination file("$buildDir/reports/jacoco")
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['**/server/**',
'**/model/**',
'**/command/**'
]
)
}))
}
}
为了在 jacoco 报告中进行过滤,需要在两个任务 jacocoTestReport
和 jacocoTestCoverageVerification
中进行排除。
示例代码
def jacocoExclude = ['**/example/**', '**/*Module*.class']
jacocoTestReport {
afterEvaluate {
getClassDirectories().setFrom(classDirectories.files.collect {
fileTree(dir: it, exclude: jacocoExclude)
})
}
}
jacocoTestCoverageVerification {
afterEvaluate {
getClassDirectories().setFrom(classDirectories.files.collect {
fileTree(dir: it, exclude: jacocoExclude)
})
}
...
}
对我来说,我必须在 2 个地方进行排除
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
afterEvaluate {
excludedClassFilesForReport(classDirectories)
}
}
jacocoTestCoverageVerification {
afterEvaluate {
excludedClassFilesForReport(classDirectories)
}
}
private excludedClassFilesForReport(classDirectories) {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: [
'com/test/a/config/**',
'com/test/b/constant/**',
'com/test/c/MainApp.class'
]
)
}))
}
Gradle 6.8.3抛出异常。
Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestReport' of type org.gradle.testing.jacoco.tasks.JacocoReport.
所以我找到了解决问题的方法
classDirectories.setFrom(
fileTree(dir: "build/classes/java/main")
.filter({file -> !file.path.contains('/dir1')})
.filter({file -> !file.path.contains('/dir2')})
.filter({file -> !file.path.contains('/dir3')})
)
对于 Kotlin 用户,这是我使用的 (gradle 6.7)
build.gradle.kts
tasks.jacocoTestReport {
// tests are required to run before generating the report
dependsOn(tasks.test)
// print the report url for easier access
doLast {
println("file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
}
classDirectories.setFrom(
files(classDirectories.files.map {
fileTree(it) {
exclude("**/generated/**", "**/other-excluded/**")
}
})
)
}
此处建议:https://github.com/gradle/kotlin-dsl-samples/issues/1176#issuecomment-610643709
对于在 Kotlin DSL 中寻找这个答案的任何人,这里是:
val jacocoExclude = listOf("**/entities/**", "**/dtos/**")
jacocoTestReport {
reports {
xml.isEnabled = true
csv.isEnabled = false
}
classDirectories.setFrom(classDirectories.files.map {
fileTree(it).matching {
exclude(jacocoExclude)
}
})
}
test {
useJUnitPlatform()
systemProperty("gradle.build.dir", project.buildDir)
finalizedBy(jacocoTestReport)
extensions.configure(JacocoTaskExtension::class) {
excludes = jacocoExclude
}
}
对于那些仍在挠头从覆盖率报告中过滤某些包的人来说,这里是使用最新库的适合我的配置。
Build tool: Gradle 6.5 (also tried for 6.7)
Coverage Tool: Jacoco 0.8.5
事情要consider/Justifications
afterScript
不需要
- 需要排除两次,一次用于报告生成和覆盖验证
- intellij IDE 建议使用
excludes
参数而不是 exclude
。两者都可以正常工作
- 在提供正则表达式时,请务必提供
.class
文件而不是 .java
文件。
- Post Gradle 5、
classDirectories
为只读字段,因此,使用classDirectories.setFrom
jacocoTestReport {
doLast {
println("See report file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
}
excludedClassFilesForReport(classDirectories)
}
jacocoTestCoverageVerification {
excludedClassFilesForReport(classDirectories)
violationRules {
rule {
limit {
minimum = 0.55
}
}
}
}
private excludedClassFilesForReport(classDirectories) {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/common/apigateway/*.class',a
'**/common/*/client/*Client*.class',
'**/configuration/*ClientConfiguration.class',
'**/model/search/*SearchService.class'
])
}))
}
check.dependsOn jacocoTestCoverageVerification
这是我在 Gradle 中使用 Jacoco 0.8.5 的工作配置:
def jacocoExclusions = [
'**/config/*Config.class',
'**/config/*Advice.class',
'**/security/*AuthorityRoles.class',
'**/*Application.class'
];
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/reports/jacocoHtml")
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: jacocoExclusions
)
}))
}
}
jacocoTestCoverageVerification {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: jacocoExclusions
)
}))
}
violationRules {
rule {
excludes = jacocoExclusions
limit {
minimum = 0.90
}
}
}
}
问题:
我有一个包含 jacoco 的项目,我希望能够过滤某些 类 and/or 包。
相关文档:
我已阅读以下文档:
官方jacoco网站: http://www.eclemma.org/jacoco/index.html
gradle的官方 jacoco 文档: https://gradle.org/docs/current/userguide/jacoco_plugin.html
官方 jacoco Github
问题,正在处理报道:
https://github.com/jacoco/jacoco/wiki/FilteringOptions
https://github.com/jacoco/jacoco/issues/14
相关 Whosebug 链接:
JaCoCo & Gradle - Filtering Options(无人回答)
Exclude packages from Jacoco report using Sonarrunner and Gradle (Not using sonar)
JaCoCo - exclude JSP from report (It seems to work for maven, I am using gradle)
JaCoCo gradle plugin exclude(无法正常工作)
Gradle Jacoco - coverage reports includes classes excluded in configuration(看起来很接近,用了doFirst
,对我没用)
我尝试过的示例:
apply plugin: 'java'
apply plugin: 'jacoco'
buildscript {
repositories {
mavenCentral()
jcenter()
}
}
repositories {
jcenter()
}
jacocoTestReport {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
test {
jacoco {
destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
classDumpFile = file("$buildDir/jacoco/classpathdumps")
excludes = ["projecteuler/**"] // <-- does not work
// excludes = ["projecteuler"]
}
}
}
问题:
如何在生成 jacoco 覆盖率报告时排除某些包和 类?
感谢,Yannick Welsch
:
在搜索 Google、阅读 Gradle 文档并浏览旧的 Whosebug 帖子后,我在官方 gradle 论坛上找到了这个答案!
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/blah/**')
}))
}
}
来源: https://issues.gradle.org/browse/GRADLE-2955
对于较早的 gradle 版本 < 5.x 可能需要使用
classDirectories = files(classDirectories.files.collect {
而不是 classDirectories.setFrom
我的 build.gradle
项目 Java/Groovy 的解决方案:
apply plugin: 'java'
apply plugin: 'jacoco'
jacocoTestReport {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**'])
})
}
}
如您所见,我成功地向 exclude:
添加了更多内容以过滤一些包。
来源: https://github.com/jaredsburrows/CS-Interview-Questions/blob/master/build.gradle
其他项目的自定义任务,例如 Android:
apply plugin: 'jacoco'
task jacocoReport(type: JacocoReport) {
reports {
xml {
enabled true // coveralls plugin depends on xml format report
}
html {
enabled true
}
}
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**'])
})
}
}
Here 是 ANT 中针对此问题的解决方案。这可以通过在 jacocoTestReport
任务下添加以下内容来适应 gradle。尽管 jacoco 并未真正记录这一点,但它似乎是目前过滤测试结果的唯一方法。
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'excluded/files/**')
})
}
这已经有一段时间了,但我只是 运行 了解了这一点。我正在为所有需要的排除而苦苦挣扎。我发现这对我来说要简单得多。如果你遵循 Maven 项目布局风格 /src/main/java 和 /src/test/java,你只需要把 buildDir/classes/main 在你的 classDirectories 配置中像这样:
afterEvaluate {
jacocoTestReport {
def coverageSourceDirs = ['src/main/java']
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/reports/jacocoHtml"
}
sourceDirectories = files(coverageSourceDirs)
classDirectories = fileTree(
dir: "${project.buildDir}/classes/main",
excludes: [
//whatever here like JavaConfig etc. in /src/main/java
]
)
}
}
对我来说,与
一起工作很好test {
jacoco {
excludes += ['codeeval/**',
'crackingthecode/part3knowledgebased/**',
'**/Chapter7ObjectOrientedDesign**',
'**/Chapter11Testing**',
'**/Chapter12SystemDesignAndMemoryLimits**',
'projecteuler/**']
}
}
如文档中所述 https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 最初被问到 所以答案是:
所以如果你问我:这不是
的问题excludes = ["projecteuler/**"]
或
excludes += ["projecteuler/**"]
但是
excludes = ["**/projecteuler/**"]
排除包*.projecteuler.*
和 test {}
在项目级别,未嵌套在 jacocoTestReport
下面的代码也将 类 排除在覆盖验证之外:
jacocoTestCoverageVerification {
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: "${project.buildDir}/classes/main",
exclude: ['**/packagename/**'])
})
}
}
对于 Gradle 版本 5.x,classDirectories = files(...)
给出弃用警告并且从 Gradle 6.0 开始根本不起作用
这是不推荐使用的排除 类:
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/exclude/**')
}))
}
}
在 gradle.properties 文件中添加以下配置
coverageExcludeClasses=["com.example.package.elasticsearch.*", "com.example.package2.*",]
一些评论提到了弃用警告。解决只需使用 getter:
afterEvaluate {
getClassDirectories().from(files(classDirectories.files.collect {
fileTree(dir: it, exclude: 'com/blah/**')
}))
}
对于Gradle6
使用类似下面的东西,因为他们制作了 classDirectories as final
,我们无法重新分配它,但是存在 setter 方法 classDirectories.setFrom
可以利用
jacocoTestReport {
reports {
xml.enabled true
html.enabled true
html.destination file("$buildDir/reports/jacoco")
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['**/server/**',
'**/model/**',
'**/command/**'
]
)
}))
}
}
为了在 jacoco 报告中进行过滤,需要在两个任务 jacocoTestReport
和 jacocoTestCoverageVerification
中进行排除。
示例代码
def jacocoExclude = ['**/example/**', '**/*Module*.class']
jacocoTestReport {
afterEvaluate {
getClassDirectories().setFrom(classDirectories.files.collect {
fileTree(dir: it, exclude: jacocoExclude)
})
}
}
jacocoTestCoverageVerification {
afterEvaluate {
getClassDirectories().setFrom(classDirectories.files.collect {
fileTree(dir: it, exclude: jacocoExclude)
})
}
...
}
对我来说,我必须在 2 个地方进行排除
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
afterEvaluate {
excludedClassFilesForReport(classDirectories)
}
}
jacocoTestCoverageVerification {
afterEvaluate {
excludedClassFilesForReport(classDirectories)
}
}
private excludedClassFilesForReport(classDirectories) {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: [
'com/test/a/config/**',
'com/test/b/constant/**',
'com/test/c/MainApp.class'
]
)
}))
}
Gradle 6.8.3抛出异常。
Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestReport' of type org.gradle.testing.jacoco.tasks.JacocoReport.
所以我找到了解决问题的方法
classDirectories.setFrom(
fileTree(dir: "build/classes/java/main")
.filter({file -> !file.path.contains('/dir1')})
.filter({file -> !file.path.contains('/dir2')})
.filter({file -> !file.path.contains('/dir3')})
)
对于 Kotlin 用户,这是我使用的 (gradle 6.7)
build.gradle.kts
tasks.jacocoTestReport {
// tests are required to run before generating the report
dependsOn(tasks.test)
// print the report url for easier access
doLast {
println("file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
}
classDirectories.setFrom(
files(classDirectories.files.map {
fileTree(it) {
exclude("**/generated/**", "**/other-excluded/**")
}
})
)
}
此处建议:https://github.com/gradle/kotlin-dsl-samples/issues/1176#issuecomment-610643709
对于在 Kotlin DSL 中寻找这个答案的任何人,这里是:
val jacocoExclude = listOf("**/entities/**", "**/dtos/**")
jacocoTestReport {
reports {
xml.isEnabled = true
csv.isEnabled = false
}
classDirectories.setFrom(classDirectories.files.map {
fileTree(it).matching {
exclude(jacocoExclude)
}
})
}
test {
useJUnitPlatform()
systemProperty("gradle.build.dir", project.buildDir)
finalizedBy(jacocoTestReport)
extensions.configure(JacocoTaskExtension::class) {
excludes = jacocoExclude
}
}
对于那些仍在挠头从覆盖率报告中过滤某些包的人来说,这里是使用最新库的适合我的配置。
Build tool: Gradle 6.5 (also tried for 6.7)
Coverage Tool: Jacoco 0.8.5
事情要consider/Justifications
afterScript
不需要- 需要排除两次,一次用于报告生成和覆盖验证
- intellij IDE 建议使用
excludes
参数而不是exclude
。两者都可以正常工作 - 在提供正则表达式时,请务必提供
.class
文件而不是.java
文件。 - Post Gradle 5、
classDirectories
为只读字段,因此,使用classDirectories.setFrom
jacocoTestReport {
doLast {
println("See report file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
}
excludedClassFilesForReport(classDirectories)
}
jacocoTestCoverageVerification {
excludedClassFilesForReport(classDirectories)
violationRules {
rule {
limit {
minimum = 0.55
}
}
}
}
private excludedClassFilesForReport(classDirectories) {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/common/apigateway/*.class',a
'**/common/*/client/*Client*.class',
'**/configuration/*ClientConfiguration.class',
'**/model/search/*SearchService.class'
])
}))
}
check.dependsOn jacocoTestCoverageVerification
这是我在 Gradle 中使用 Jacoco 0.8.5 的工作配置:
def jacocoExclusions = [
'**/config/*Config.class',
'**/config/*Advice.class',
'**/security/*AuthorityRoles.class',
'**/*Application.class'
];
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/reports/jacocoHtml")
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: jacocoExclusions
)
}))
}
}
jacocoTestCoverageVerification {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: jacocoExclusions
)
}))
}
violationRules {
rule {
excludes = jacocoExclusions
limit {
minimum = 0.90
}
}
}
}