• Java如何对增量代码进行单测覆盖率统计?
  • 发布于 2个月前
  • 110 热度
    0 评论
目的
对于代码质量的把控,除了对全量单测覆盖率有要求,应该对每次合并到主分支代码的单测也有要求,不然会导致全量单测覆盖率逐步降低。这里就对增量代码提出了要求:什么是增量代码、增量代码怎么统计、增量代码的单测覆盖率怎么统计。这里介绍下如何使用 git 和 Jacoco 对 Java 增量代码的单测覆盖率进行统计。

增量代码
这里对增量代码进行如下的定义:一次 commit 或者 MR/PR 中,修改或增加的代码,即存在 diff 的代码,都视为增量代码。对于增量代码的判断,其实很简单,可以通过对 git diff 的结果进行解析来实现。

git diff
diff 命令使用
git diff branch 可以输出当前分支代码与 branch 之间的差异,通过指定参数-U0,可以输出不含有上下文信息的 diff 信息:
# 堆代码 duidaima.com
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 59ad23f..2f958a8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,7 +11,5 @@ variables:
-  1a
-  2b
-  3c
-  4d
-  5e
-  6f
-  7g
+
+  2w
+  3x
+  4y
+  5z
@@ -29 +26,0 @@ stages:
-  - deploy
@@ -74,0 +72 @@ build:
+  - test
参数 _-U<n> --unified=<n>_,用来表示在进行生成 diff 的时候,上下文行数,默认是 3。

解读  git diff  的结果
git diff 输出结果是有格式的,通过对 git diff 输出结果进行解析,主要是为了获取增量代码发生的行号。

第一部分

表示发生变更的文件,a 是变更前的版本,b 是变更后的版本。

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
第二部分
.index 表明是接下来是哈希索引信息
.59ad23f..2f958a8 表示两个版本的 git 哈希值
.最后 6 位数字是对象的模式,100644 表示是普通文件,权限为 644。
index 59ad23f..2f958a8 100644
此外,对于新增、删除、重命名等,第二行还可能是其他的形式:
// 新增
diff --git a/file1 b/file1
new file mode 100644
index 0000000..c124acb


// 删除
diff --git a/file1 b/file1
deleted file mode 100644
index 2652f5f..0000000


// 复制
diff --git a/a b/b
copy from a/a
copy to b/b
index c124acb..2652f5f


// 重命名
diff --git a/a b/b
rename from a/a
rename to b/b
index c124acb..2652f5f
第三部分
"---"表示变动前的文件,"+++"表示变动后的文件。
最后一部分
具体的变更信息,每一处变更均以 @@ 开头,对于此处变更则表示:
原来版本的第 11 行开始,接下来的 7 行都被删除(-号)了;
在新版本中,从第 11 行开始,5 行为新增(+号)内容。
@@ -11,7 +11,5 @@ variables:
-  1a
-  2b
-  3c
-  4d
-  5e
-  6f
-  7g
+
+  2w
+  3x
+  4y
+  5z
git 中没有修改的概念,修改即为删除+新增,逻辑简单,更切合增量的含义。

通过对于 git diff 的结果进行解析,我们能够得到增量代码发生的行号。

增量覆盖率生成
jacoco.xml
Jacoco 除了输出一份 HTML 的结果文件外,还有一份 jacoco.xml xml 结果文件,_jacoco.xml_ 中详细描述了文件中每一行的单测情况。
jacoco.xml 中详细描述了代码中每一行的单测情况:
<sourcefile name="Abc.java">
    <line nr="1" mi="0" ci="2" mb="1" cb="1"/>
    <line nr="2" mi="3" ci="0" mb="0" cb="0"/>
    <line nr="4" mi="0" ci="2" mb="0" cb="0"/>
</sourcefile>
如果 jacoco.xml 没有这一行代码的数据,则表示该行不需要单测,例如空白行、{等。上述第 3 行即为该情况。

对于一个 line 元素 <line nr="1" mi="0" ci="2" mb="1" cb="1"/>:
nr 表示是 Abc 源码的第 1 行
ci=2 表示覆盖到的指令为 2
mb=1 表示缺少 1 的分支测试
cb=1 表示覆盖到 1 次分支测试
xml 与 html 对应关系
xml 对应到 html 的样式:
指令覆盖 mi=0 mi>0
ci=0 -- 红色(nc)
ci>0 绿色(fc) 黄色(pc)
分支覆盖 mb=0 mb>0
------------ --------- ---------
cb=0 -- 红钻(bnc)
cb>0 绿钻(bfc) 黄钻(bpc)
b: branch f: full c: cover P: partial N: not

增量单测结果计算
增量行:通过对 git diff 结果解析得到增量的行号
新增行 = 增量行 - 无需单测的行
指令覆盖率:新增行 ci / (新增行 ci + 新增行 mi )
分支覆盖率:新增行 cb / (新增行 cb + 新增行 mb )
行覆盖率:新增行具备单测的行数 / 新增行总行数
新增行中是否有被单测覆盖到,可以通过下面方式判断:ci > 0 || cb > 0。
用户评论