使用 Gradle 过滤 JaCoCo 覆盖率报告
Posted
技术标签:
【中文标题】使用 Gradle 过滤 JaCoCo 覆盖率报告【英文标题】:Filter JaCoCo coverage reports with Gradle 【发布时间】:2015-07-05 10:30:13 【问题描述】:问题:
我有一个jacoco 的项目,我希望能够过滤某些类和/或包。
相关文档:
我已阅读以下文档:
官方jacoco网站: http://www.eclemma.org/jacoco/index.html
gradle 的官方 jacoco 文档: https://gradle.org/docs/current/userguide/jacoco_plugin.html
官方jacocoGithub
问题,正在处理报道:
https://github.com/jacoco/jacoco/wiki/FilteringOptions
https://github.com/jacoco/jacoco/issues/14
相关 *** 链接:
JaCoCo & Gradle - Filtering Options(无应答)
Exclude packages from Jacoco report using Sonarrunner and Gradle(不使用sonar)
JaCoCo - exclude JSP from report(它似乎对maven有效,我正在使用gradle)
Maven Jacoco Configuration - Exclude classes/packages from report not working(它似乎适用于maven,我正在使用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 覆盖率报告时排除某些包和类?
【问题讨论】:
第三方选项(我是 FD 的创始人):如果您将报告上传到 Codecov,您可以在功能部分中忽略任何您喜欢的文件的产品。谢谢。 @StevePeak 所以你可以使用Codecov
在线过滤packages
?另外,我看到了Github
,android
支持呢,我看到了Java
。我仍然应该将所有报告发送给您,然后在过滤之后过滤。
您可以根据您不想包含的任何文件的正则表达式方法进行过滤。通过 Jacoco 报告支持所有 java。只是在 Codecov 工作后进行过滤。它会记住您的过滤器并将其应用于所有未来的报告。谢谢!
我很好奇;那么官方文档中的excludes
实际做什么 呢?它几乎没用吗?
那个excludes
不在覆盖任务上,而是在测试任务上。它排除了 JaCoCo 检测的文件,从而记录了覆盖率。如果您不想记录某些类的覆盖率,如果由于与另一个检测代理发生冲突而无法记录,或者因为您预先检测了类,则可以使用它。这不会从报告中排除一个类,尤其是在提到的最后一种情况下,这将是一个可怕的想法。
【参考方案1】:
感谢Yannick Welsch
:
在搜索 Google、阅读 Gradle 文档并浏览旧的 *** 帖子后,我在官方 gradle 论坛上找到了这个答案!
jacocoTestReport
afterEvaluate
classDirectories.setFrom(files(classDirectories.files.collect
fileTree(dir: it, exclude: 'com/blah/**')
))
来源: https://issues.gradle.org/browse/GRADLE-2955
对于旧的 gradle 版本 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/**'])
)
来源: https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/gradle/quality.gradle#L59
【讨论】:
@BradPitcher 没问题!我花了一段时间才找到正确的答案。它看起来很“hackish”。我希望他们能想出更好的方法。 类似:exclude: ['**/*Test*.*'])
jacocoTestReport
仅适用于 jacoco
和 java
插件。这不适用于安卓。请在此处查看我的 android 仓库:github.com/jaredsburrows/android-gradle-java-template/blob/…
classDirectories =
会导致此警告。 The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...)
。展示与 Gradle 6.0 兼容的解决方案会很棒。
使用此配置获取Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestReport' of type org.gradle.testing.jacoco.tasks.JacocoReport
。使用 gradle 5.6 和 Java 8【参考方案2】:
对于 Gradle 版本 5.x,classDirectories = files(...)
会发出弃用警告,并且从 Gradle 6.0 开始根本不起作用
这是不推荐使用的排除类的方式:
jacocoTestReport
afterEvaluate
classDirectories.setFrom(files(classDirectories.files.collect
fileTree(dir: it, exclude: 'com/exclude/**')
))
【讨论】:
或者简单地使用 classDirectories.from (追加到列表而不是覆盖列表) 您将在exclude:
之后添加[]
以包含多个路径。
太好了,我使用 gradle 6.0.1,这个解决方案对我有用。
这行得通,有人可以解释一下到底发生了什么
我已更改接受的答案以反映此更改【参考方案3】:
对我来说,和我一起工作很好
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
中
【讨论】:
这似乎给类 0% 的覆盖率,而不是完全忽略它们。我正在使用 JaCoCi 0.8.5 和 Gradle 6.0 这是告诉jacoco不要干预某些课程的正确方法,其他方法只会影响报告部分。【参考方案4】:对于 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/**'
]
)
))
【讨论】:
我正在尝试在 build.gradle 中使用下面的 sn-p 来排除我的 dto,但它不起作用。我正在使用 gradle 6.6.1 版本。让我知道是否有任何变化: 它,排除: ['/dto/' ] )) 【参考方案5】:为了在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)
)
...
【讨论】:
【参考方案6】:Here 是 ANT 中这个问题的解决方案。这可以通过在jacocoTestReport
任务下添加以下内容来适应 gradle。尽管 jacoco 并没有真正记录这一点,但它似乎是目前过滤测试结果的唯一方法。
afterEvaluate
classDirectories = files(classDirectories.files.collect
fileTree(dir: it, exclude: 'excluded/files/**')
)
【讨论】:
好的,感谢您确认我的发现是正确的!我希望它们使将来过滤变得更容易,或者简单地记录如何使用 Gradle 进行过滤。 有什么方法可以将源集排除在 jacoco 报告中吗?我想排除位于generated/java/
而不是main/java
的所有源文件。
这不适用于干净的构建。 afterEvaluate 在 Gradle 的配置阶段运行,该阶段是在任何任务执行之前和编译任何类之前。所以类目录将为空【参考方案7】:
这已经有一段时间了,但我刚刚遇到了这个。我正在为所有需要的排除而苦苦挣扎。我发现这对我来说要简单得多。如果您遵循 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
]
)
【讨论】:
刚刚又看到了。这直接取自工作配置。也许您的 Gradle 和 Jacoco 版本与我的不同。对不起。【参考方案8】:下面的代码也将类排除在覆盖率验证之外:
jacocoTestCoverageVerification
afterEvaluate
classDirectories = files(classDirectories.files.collect
fileTree(dir: "$project.buildDir/classes/main",
exclude: ['**/packagename/**'])
)
【讨论】:
嘿,您的版本抛出以下异常消息:“无法设置只读属性 'classDirectories' 的值”。通过更改 classDirectories -> classDirectories.from 修复。但不幸的是,我的包仍然存在于报告中【参考方案9】:对于那些仍想从覆盖报告中过滤某些包的人来说,这里是适合我使用最新库的配置。
Build tool: Gradle 6.5 (also tried for 6.7)
Coverage Tool: Jacoco 0.8.5
需要考虑的事项/理由
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
【讨论】:
【参考方案10】:对我来说,我必须在 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'
]
)
))
【讨论】:
【参考方案11】:对于 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
【讨论】:
【参考方案12】:对于任何想在 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
【讨论】:
【参考方案13】:一些 cmets 提到了弃用警告。只需使用 getter 即可解决:
afterEvaluate
getClassDirectories().from(files(classDirectories.files.collect
fileTree(dir: it, exclude: 'com/blah/**')
))
【讨论】:
【参考方案14】:在 gradle.properties 文件中添加下面的配置
coverageExcludeClasses=["com.example.package.elasticsearch.*", "com.example.package2.*",]
【讨论】:
coverageExcludeClasses
在 JaCoCo/Gradle 中似乎不是一个东西【参考方案15】:
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'))
)
【讨论】:
【参考方案16】:这是我在 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
【讨论】:
以上是关于使用 Gradle 过滤 JaCoCo 覆盖率报告的主要内容,如果未能解决你的问题,请参考以下文章
使用 Sonarrunner 和 Gradle 从 Jacoco 报告中排除包
使用Sonarrunner和Gradle从Jacoco报告中排除软件包