为什么Intellij代码覆盖率和jacoco代码覆盖率显示不同的百分比?

时间:2019-10-30 14:37:41

标签: java gradle intellij-idea code-coverage jacoco

我在intellij中有一个gradle项目(java)。我右键单击intellij中的项目,然后运行Run Tests in projectName with coverage,它在右侧创建了一些测试报告。在右手边,我有类似的数字

| Class, %   | Method, %   | Line, %
--------------------------------------
80%(80/100)  50%(100/200)  30%(30/100)

注意:以上数字仅作为示例。这些不是真实的。

现在,我进入命令行并运行gradlew jacocoTestReport,它为方法和行提供了different set of numbers,但给了Class numbers were same。为什么在这种情况下会有差异?

是否可以通过命令行而不是右键单击来运行intellij的代码覆盖率?

我只想知道Intellij是否使用不同于jacoco的其他方法来计算这些数字。但是即使在那种情况下,我的假设是只有一种方法可以计算东西对吗?还是intellij或jacoco不会对具有Lombok注释等的类进行计数,从而减少最终计数中方法(获取器和设置器)的数量?

2 个答案:

答案 0 :(得分:1)

我在一个相关的任务中偶然发现了这个问题,尽管它很旧,但我认为对某些人来说仍然很有趣。

方法编号

主要问题是intellij的覆盖率和jacoco的计算数字是否不同,哪种方法是正确的。简短的答案:intellij覆盖摘要使用开发人员直接提供的方法,而jacoco在字节码级别上运行并显示在那里找到的方法数量。为了证明这一点,我用四个方法创建了一个简单的类:

public class Exp {

    private final LinkedList<Integer> vals = new LinkedList<>();

    public void addVal(int v) {
        vals.add(v);
    }

    public List<Integer> doubled() {
        return vals.stream().map(x -> x*2).collect(Collectors.toList());
    }

    public List<Integer> evens() {
        return vals.stream().filter(x -> x%2 == 0).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        Exp t = new Exp();

        t.addVal(1);
        t.addVal(2);
        t.addVal(3);

        System.out.println(t.doubled());
        System.out.println(t.evens());
    }
}

在intellij摘要中,右侧显示以下值:

intellij coverage summary

因此方法的数量等于示例代码中的方法的数量。从报告中可以看出,Jacoco报告了七种方法(与eclipse 2020-09中的Emma插件相同): jacoco test report

这是我们可以在字节码中找到的方法的数量,例如通过使用javap disassembler命令。在这里,我们看到两个lambda表达式作为类的方法实现,并且还插入了标准构造函数。

C:\_workspace\intellij\Tests\out\production\mod>javap -p Exp.class
Compiled from "Exp.java"
public class Exp {
  private final java.util.LinkedList<java.lang.Integer> vals;
  public Exp();
  public void addVal(int);
  public java.util.List<java.lang.Integer> doubled();
  public java.util.List<java.lang.Integer> evens();
  public static void main(java.lang.String[]);
  private static boolean lambda$evens$1(java.lang.Integer);
  private static java.lang.Integer lambda$doubled$0(java.lang.Integer);
}

使我感到困惑的是,Intellij覆盖率报告(运行->生成Corevage报告)显示了五种方法:

intellij coverage report

在代码中添加标准构造函数并重新生成报告,这表明该报告包括所生成的标准构造函数,但不包括lambda表达式。似乎有一种中间计数方法。

至于intellij还是jacoco是正确的问题,我都说它们都是正确的,这只是定义问题。

行号

在我的测试中,所有报告均显示一致的行号。在上面的示例中,报告了包含可执行代码的13行。我对覆盖范围摘要中的intellij行数的印象是,它不会一直正确刷新。可能需要进行彻底的重建。

答案 1 :(得分:0)

我注意到我使用的 @Test 注释来自 org.junit.jupiter.api.Test,而 Jacoco 并没有使用它。将导入更改为 import org.junit.Test 修复了我的覆盖问题。