java - Jacoco 代码覆盖率随着迁移到 Java 11 而下降
问题描述
我有几个使用 Java 8 构建的 Gradle 项目,最近将它们转换为使用 Java 11 后,Jacoco 代码覆盖率报告报告的百分比比以前低得多。在一个项目中,在过渡后立即,我的覆盖率从 81% 下降到 16%。
我尝试将 Jacoco 插件更新到 0.8.3(具有官方JDK 11 支持),将 Gradle 更新到 5.4,并将 TestNG 更新到 6.14.3(不确定这是否有任何影响;认为使用最新版本不会有什么坏处)。即使经过这些更改,我上面提到的项目也有 16% 的覆盖率。我手动检查了一些报告覆盖率为 0% 的类,发现它们确实有测试覆盖率。
例如,我将此方法添加到我的一个类中:
public String helloWorld(){
return "hello";
}
然后我在测试中使用它:
@Test(groups = IntegrationTest.INTEGRATION_GROUP)
public void testHelloWorld() {
String helloWorld = authManager.helloWorld();
assertEquals(helloWorld, "hello");
}
覆盖率报告为 0:
如果有帮助,这是我的 Jacoco Gradle 设置。我正在使用自定义插件来配置它们。
class ManagedJacocoPlugin implements ManagedPlugin {
@Override
void apply(PluginManager pluginManager) {
pluginManager.apply(JacocoPlugin.class)
}
@Override
void configure(Project project, GradlePluginConfig pluginConfig) {
def jacoco = project.extensions.getByName("jacoco")
jacoco.toolVersion = "0.8.3"
def jacocoTestReport = project.tasks.getByName('jacocoTestReport')
jacocoTestReport.reports {
xml.enabled false
csv.enabled false
}
project.tasks.withType(Test).each { t ->
t.jacoco {
destinationFile = project.file("$project.buildDir/jacoco/test.exec")
}
}
jacocoTestReport.dependsOn "integrationTest"
}
}
据我所知,鉴于我使用的工具版本,Java 11 应该完全支持 Jacoco 覆盖范围。我在这里想念什么?
解决方案
这是https://stackoverflow.com/help/mcve关于如何创建最小、完整和可验证示例的页面:
确保它是完整的
将问题中的代码复制到新文件或项目中,然后运行它。如果它不为您运行,那么它不会为其他任何人运行。
但是谁知道ManagedPlugin
你的例子是什么?
但是,好吧,让我们尝试遵循上述建议并使用我们所拥有的,假装我们有时间猜测并且我们很幸运能够正确猜测。
除了ManagedPlugin
添加许多缺失的部分之外的所有内容都成为以下内容build.gradle
apply plugin: 'java'
apply plugin: 'jacoco'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'org.testng', name: 'testng', version: '6.14.3'
}
test {
useTestNG() {
includeGroups('unit')
}
}
task integrationTest(type: Test, dependsOn: ['test']) {
useTestNG() {
includeGroups('integration')
}
}
def jacoco = project.extensions.getByName("jacoco")
jacoco.toolVersion = "0.8.3"
def jacocoTestReport = project.tasks.getByName('jacocoTestReport')
jacocoTestReport.reports {
xml.enabled false
csv.enabled false
}
project.tasks.withType(Test).each { t ->
t.jacoco {
destinationFile = project.file("$project.buildDir/jacoco/test.exec")
}
}
jacocoTestReport.dependsOn "integrationTest"
方法helloWorld
进入src/main/Example.java
class Example {
public String helloWorld() {
return "hello";
}
}
方法testHelloWorld
进入src/test/ExampleTest.java
import org.testng.annotations.Test;
import static org.testng.Assert.*;
class ExampleTest {
Example authManager = new Example();
@Test(groups = "integration")
public void testHelloWorld() {
String helloWorld = authManager.helloWorld();
assertEquals(helloWorld, "hello");
}
}
gradle clean jacocoTestReport
使用 Gralde 5.4 和 JDK 11.0.1 的执行产生以下报告
因此,我们可以得出结论,提供的示例绝对不完整。
让我们尝试再次猜测并添加到src/main/java/Example.java
public void anotherMethod() {
}
并进入src/test/java/ExampleTest.java
@Test(groups = "unit")
public void test() {
new Example().anotherMethod();
}
现在执行gradle clean jacocoTestReport
产生以下报告
似乎现在我们可以重现您的问题。
为什么anotherMethod
不覆盖?让我们遵循https://stackoverflow.com/help/mcve的另一个好建议:
分而治之。当您有少量代码,但问题的根源完全不清楚时,开始一次删除代码,直到问题消失 - 然后添加最后一部分。
这不仅适用于代码,还适用于版本的更改 - 让我们尝试将 Gradle 版本的更改从 5.4 逆转回 4.10.3 并执行gradle clean jacocoTestReport
生产
因此我们可以得出结论,Gradle 中的某些内容发生了变化。让我们检查一下它的变更日志 - https://docs.gradle.org/5.0/release-notes.html包含一个非常有趣的声明:
JaCoCo 插件现在可以与构建缓存和并行测试执行一起使用
...以代码覆盖率运行的任务被配置为在它们开始执行之前删除执行数据...
任务integrationTest
删除任务收集的数据test
。让我们尝试不使用相同的文件:
//project.tasks.withType(Test).each { t ->
// t.jacoco {
// destinationFile = project.file("$project.buildDir/jacoco/test.exec")
// }
//}
jacocoTestReport.executionData(test)
jacocoTestReport.executionData(integrationTest)
gradle clean jacocoTestReport
现在即使使用 Gradle 5.4执行也会产生
推荐阅读
- excel - 在 VBA 中使用当前区域会破坏我的 Excel
- python-3.x - 如何在 Gurobi 中获得导致最佳结果的所有解决方案
- flutter - Flutter:将价格本地化限制为仅限英文
- ios - UIView 作为 UITableView 的标头
- javascript - 使引导下拉菜单显示在模式顶部的方法
- python - 删除空元素嵌套列表的 Pythonic 方式和节省时间
- typescript - 动态导入 Typescript 文件作为基于 json 的配置的替代方案
- javascript - 移动的组件不做它的工作(react-redux)
- java - REST API 作业调度
- mysql - 为什么我的 JS 代码不能识别 mysql 数据库?