【问题标题】:Jacoco code coverage dropped with migration to Java 11Jacoco 代码覆盖率随着迁移到 Java 11 而下降
【发布时间】:2019-09-14 06:41:22
【问题描述】:

我有几个使用 Java 8 构建的 Gradle 项目,最近将它们转换为使用 Java 11 后,Jacoco 代码覆盖率报告报告的百分比比以前低得多。在一个项目中,刚过渡后,我的覆盖率从 81% 下降到 16%。

我尝试将 Jacoco 插件更新到 0.8.3(有官方 JDK 11 support),将 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 覆盖范围。我在这里错过了什么?

【问题讨论】:

  • 请阅读stackoverflow.com/help/mcve 并提供完整 可验证测试示例以及覆盖率报告为0的相应类。
  • 谢谢@Godin,会的

标签: java code-coverage jacoco java-11


【解决方案1】:

以下是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");
    }
}

使用 Gralde 5.4 和 JDK 11.0.1 执行 gradle clean jacocoTestReport 会产生以下报告

因此我们可以得出结论,提供的示例肯定不完整。

让我们再次尝试猜测并添加到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 也会产生

【讨论】:

  • 太棒了,谢谢戈丁!在过去的几天里,我偶然发现代码覆盖率需要“测试”任务才能准确报告,但我不知道为什么。一旦我将该任务添加为对 integrationTest 的依赖项,覆盖率就会返回。这是一个更清洁的解决方案。再次感谢您的彻底回答。
猜你喜欢
  • 2016-11-11
  • 2019-01-02
  • 2012-11-02
  • 2014-11-09
  • 2016-11-08
  • 2018-05-28
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多