单元测试 - 如何使用 Jacoco 计算线路覆盖率

Anu*_*ool 4 android unit-testing jacoco

我对计算线路覆盖范围有点困惑。

这是 Jacoco 生成的报告的快照 -

在此输入图像描述

每个标签的含义是什么?- Instruction,,,,,, .branchcomplexityline​​methodclass

M另外andC代表什么?

Aru*_*gal 5

M表示缺失行数/占总数的百分比,C表示覆盖行数/占总数的百分比。

\n\n

PS:Jacoco Jenkins 仪表板仅显示“缺失”和“覆盖”(总计),但不显示“总数/值/%”。但是如果您使用 Gradle 的jacocoTestReport任务生成的报告(即 index.html),那么它只显示错过的 #s/percentage 和不显示 Covered#s/%(我猜,在这个如果您知道遗漏了多少以及总共有多少,则剩余#/% 已涵盖)。\n好处是,如果您匹配/计算这 2 个报告提供的缺失/覆盖/总计信息,即 .html (index.html) 中的信息或您在 Jenkins 作业仪表板中看到的信息(Jacoco 插件读取.exec 文件也是如此),它们匹配!(因为它们是由相同的 .exec 文件生成的)。

\n\n

有关更多详细信息,请参阅 Jacoco 覆盖计数器。

\n\n

您可以查看代码覆盖率它尝试显示哪种覆盖率报告标题。

\n\n

http://www.eecis.udel.edu/~zmanchun/vsl_osx64-1.1/src/jacoco/doc/counters.html

\n\n

覆盖计数器

\n\n

JaCoCo 使用一组不同的计数器来计算覆盖率指标。所有这些计数器都源自 Java 类文件中包含的信息,这些信息基本上是 Java 字节码指令和可选地嵌入类文件中的调试信息。即使没有可用的源代码,这种方法也可以对应用程序进行高效的动态检测和分析。在大多数情况下,收集到的信息可以映射回源代码并可视化到行级粒度。无论如何,这种方法有其局限性。类文件必须使用调试信息进行编译,以计算行级覆盖率并提供源代码突出显示。并非所有 Java 语言结构都可以直接编译为相应的字节码。在这种情况下,Java 编译器会创建所谓的合成代码,有时会导致意外的代码覆盖结果。

\n\n

说明(C0 覆盖范围)

\n\n

JaCoCo 计数的最小单位是单个 Java 字节代码指令。指令覆盖率提供有关已执行或错过的代码量的信息。该指标完全独立于源格式,并且始终可用,即使类文件中没有调试信息也是如此。

\n\n

分支机构(C1 覆盖范围)

\n\n

JaCoCo 还计算所有 if 和 switch 语句的分支覆盖率。该指标计算方法中此类分支的总数,并确定已执行或错过的分支的数量。即使类文件中没有调试信息,分支覆盖率也始终可用。请注意,在此计数器定义的上下文中,异常处理不被视为分支。

\n\n

如果类文件已使用调试信息进行编译,则决策点可以映射到源代码行并相应地突出显示:

\n\n
No coverage: No branches in the line has been executed (red diamond)\nPartial coverage: Only a part of the branches in the line have been executed (yellow diamond)\nFull coverage: All branches in the line have been executed (green diamond)\n
Run Code Online (Sandbox Code Playgroud)\n\n

圈复杂度

\n\n

JaCoCo 还计算每个非抽象方法的圈复杂度,并总结类、包和组的复杂度。根据 McCabe1996 的定义,圈复杂度是可以(线性)组合通过某种方法生成所有可能路径的最小路径数。因此,复杂度值可以作为完全覆盖某个软件的单元测试用例数量的指示。即使类文件中没有调试信息,也始终可以计算复杂性数字。

\n\n

圈复杂度 v(G) 的正式定义基于将方法的控制流图表示为有向图:

\n\n
v(G) = E - N + 2 \n
Run Code Online (Sandbox Code Playgroud)\n\n

其中 E 是边数,N 是节点数。JaCoCo 根据分支数 (B) 和决策点数 (D) 使用以下等效方程计算方法的圈复杂度:

\n\n
v(G) = B - D + 1 \n
Run Code Online (Sandbox Code Playgroud)\n\n

根据每个分支的覆盖状态,JaCoCo 还计算每个方法的覆盖和错过的复杂性。错过的复杂性再次表明缺少完全覆盖模块的测试用例的数量。请注意,由于 JaCoCo 不考虑异常处理,因此分支 try/catch 块也不会增加复杂性。\n

\n\n

对于所有已使用调试信息编译的类文件,可以计算各个行的覆盖信息。当分配给源行的至少一条指令已被执行时,该源行被视为已执行。

\n\n

由于单行通常编译为多个字节代码指令,因此源代码突出显示为包含源代码的每行显示三种不同的状态:

\n\n
No coverage: No instruction in the line has been executed (red background)\nPartial coverage: Only a part of the instruction in the line have been executed (yellow background)\nFull coverage: All instructions in the line have been executed (green background)\n
Run Code Online (Sandbox Code Playgroud)\n\n

方法

\n\n

每个非抽象方法至少包含一条指令。当至少一条指令已执行时,方法被视为已执行。由于 JaCoCo 在字节码级别工作,因此构造函数和静态初始化程序也被视为方法。其中一些方法可能在 Java 源代码中没有直接对应关系,例如隐式并因此生成的默认构造函数或常量初始值设定项。

\n\n

课程

\n\n

当一个类至少有一个方法被执行时,该类就被视为已执行。请注意,JaCoCo 将构造函数和静态初始值设定项视为方法。由于 Java 接口类型可能包含静态初始化程序,因此此类接口也被视为可执行类。\nJaCoCo 0.6.3.20130409-1102 版权所有 \xc2\xa9 2009, 2013 Mountainminds GmbH & Co. KG 和贡献者

\n