sanor通过jacoco插件收集代码覆盖率

简介

单元测试是保证代码质量的重要一环,而如何衡量单元测试写得好不好呢?覆盖率(Coverage)是一个重要指标。而JaCoCo则是专门为Java提供的用于检测测试覆盖率的工具,英文全称为Java Code Coverage

基本概念

这里所讲的覆盖率是指测试代码的覆盖率,这个指标有多种计算方式,如下是比较常用的有:

  • 行覆盖率:执行代码行数 / 总代码行数,判断有多少行代码被测试执行;
  • 类覆盖率:执行的类 / 代码中类总个数;
  • 分支覆盖率:执行的逻辑分支数 / 总的分支数,一般用于检测是不是lf/else都有测试覆盖;
  • 方法覆盖率:执行的方法数 / 代码总方法数,检测是否有方法被遗漏,构造方法也看作为方法。
  • 圈复杂度:用于判断代码结构的复杂程序,JaCoCo不考虑异常处理的分支;一般认为圈复杂度大于10,就存在比较大的风险,严格要求不可大于15。

颜色标识:

JaCoCo会通过颜色来标识代码覆盖情况,使其一目了然。红色表示没有覆盖,绿色表示已经覆盖,黄色表示部分覆盖。

执行方式:

执行JaCoCo有多种方式:

(1)直接通过命令执行:https://www.eclemma.org/jacoc...

(2)Ant执行:https://www.eclemma.org/jacoc...

(3)Maven执行:https://www.eclemma.org/jacoc...

(4)集成IDE执行:https://www.eclemma.org/

我们接下来主要讲解maven的方式。

maven整合

基础整合

Maven整合JaCoCo也容易,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!--maven测试为 default 生命周期中的test阶段。-->
<!--test阶段与 maven-surefire-plugin 的test目标相绑定了, 这是一个内置的绑定。-->
<!--Maven通过插件来执行 JUnit 和 TestNG 的测试用例。-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>

<!--执行单元测试命令:mvn test-->
<!--结果在target目录下生产jacoco-unit.exec文件,表明jacoco正确执行-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<configuration>
<!--指定生成 .exec 文件的存放位置-->
<destFile>target/coverage/jacoco-unit.exec</destFile>
<!--Jacoco 是根据 .exec 文件生成最终的报告,所以需指定 .exec 的存放路径-->
<dataFile>target/coverage/jacoco-unit.exec</dataFile>
<!--指定某些类不执行检测:-->
<!--<excludes>
<exclude>com/pkslow/basic/containsperformance/**</exclude>
<exclude>com/pkslow/basic/ReadPropertiesFile</exclude>
</excludes>-->

</configuration>

<!-- 执行的单测内容 -->
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

规则与阈值

Rules标签可以指定检查阈值,比如类覆盖率必须为100%。在configuration里面配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<rules>
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>  
<limit implementation="org.jacoco.report.check.Limit">
<counter>METHOD</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>
<limit implementation="org.jacoco.report.check.Limit">
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>
<limit implementation="org.jacoco.report.check.Limit">
<counter>CLASS</counter>
<value>MISSEDCOUNT</value>
<maximum>0</maximum>
</limit>
</limits>
</rule>
</rules>

这时需要有下面的check才会执行这个规则校验:

1
2
3
4
5
6
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
</execution>

如果不满足条件,maven build就会失败。不过,如果我们集成了SonarQube,我们则会通过SonarQube来设置这个规则和阈值。

提交到Sonar

添加SonarQube配置信息如下,有三种配置方式:

(1)配置数据库信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.jdbc.url>jdbc:postgresql://localhost/sonar</sonar.jdbc.url>
<sonar.jdbc.driver>org.postgresql.Driver</sonar.jdbc.driver>
<sonar.jdbc.username>user</sonar.jdbc.username>
<sonar.jdbc.password>password</sonar.jdbc.password>
<sonar.host.url>http://localhost:9000</sonar.host.url>
</properties>
</profile>
</profiles>

(2)配置用户名密码

1
2
3
4
5
6
7
8
9
10
11
12
13
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.login>admin</sonar.login>
<sonar.password>admin</sonar.password>
</properties>
</profile>
</profiles>

(3)配置令牌

1
2
3
4
5
6
7
8
9
10
11
12
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.login>9656c84090b2481db6ea97b6d14d87d546bff619</sonar.login>
</properties>
</profile>
</profiles>

以上三种都可以,配置完成后,执行命令如下:

1
mvn clean verify sonar:sonar

如果不想添加配置,可以直接通过命令来指定,命令如下:

1
mvn clean verify sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.login=9656c84090b2481db6ea97b6d14d87d546bff619