在我们实际的工作中,当完成程序的开发后,需要提交给测试人员进行测试,经过测试人员测试后,代码才能上线到生产环境。
有个问题是:怎么能证明程序得到了充分的测试,程序中所有代码都被走到了。当然,代码覆盖率只能作为测试后的一个参照,如果最开始的需求都理解错了,那么再高的代码覆盖率,都失去了意义。
那么这时就需要引入代码覆盖率这个东东了,要统计 C++ 的代码覆盖率有 GCover,统计 Java 的代码覆盖率则有 JaCoCo 可以实现。
JaCoCo 是一个免费的Java代码覆盖率检测工具,可以统计到测试对以下内容的覆盖情况:
对各种覆盖率的具体含义可以参考官方文档:https://www.jacoco.org/jacoco/trunk/doc/counters.html
使用 JaCoCo 生成覆盖率时,可以使用 on-the-fly 方式,对程序的原代码是无侵入式的,只是在启动 jar 包时,增加一个参数就行,可确保测试人员测试的代码,和上线到生产环境的代码一致。
为了简单起见,这里直接基于 springboot 创建被测试的类,使用了 RequestMapping 注解。
package com.test.JacocoTest.controler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping
public class Athytics {
@GetMapping("/+/{a}/{b}")
public int add(@PathVariable("a") Integer param1, @PathVariable("b") Integer b){
int result = 0;
if(param1 < 0 || param1 > 1000){
result = b - param1;
}else{
result = param1 + b - 1000;
}
return result;
}
@GetMapping("/-/{a}/{b}")
public int minus(@PathVariable("a") Integer param1, @PathVariable("b") Integer b){
return param1 - b;
}
@GetMapping("/*/{a}/{b}")
public int multiply(@PathVariable("a") Integer param1, @PathVariable("b") Integer b){
return param1 * b;
}
@GetMapping("///{a}/{b}")
public int divide(@PathVariable("a") Integer param1, @PathVariable("b") Integer b){
return param1 / b;
}
@GetMapping("/c/{a}/{b}")
public String power(@PathVariable("a") Integer param1, @PathVariable("b") Integer b){
return String.valueOf(Math.round(Math.pow(param1, b)-1));
}
@GetMapping("/abs/{a}")
public String abs(@PathVariable("a") Integer param1){
return String.valueOf(Math.round(Math.abs(param1)));
}
}
创建 SpringBoot 的启动类:
package com.test.JacocoTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JacocoTestApplication {
public static void main(String[] args) {
SpringApplication.run(JacocoTestApplication.class, args);
}
}
代码结构非常简单
可以进入到官方页面下载 https://search.maven.org/search?q=g:org.jacoco
下载其中需要用到的两个包即可
Jacoco 工具包及被测试包如下
指定需要检查测试对代码覆盖情况的包名,采集Jacoco覆盖率文件的ip及端口
java -javaagent:jacocoagent.jar=includes=com.test.*,output=tcpserver,port=6301,address=localhost,append=false -jar JacocoTest-1.0-SNAPSHOT.jar
因为是使用的 Springboot 开发框架,可以直接打开浏览器进行测试。
输入如下URL: http://localhost:9999/+/12/25
指定要从何处获取jacoco统计数据,地址及端口应与 2.2 中的启动参数中一致
java -jar jacococli.jar dump --address localhost --port 6301 --destfile jacoco.exec --reset
参数说明:
--reset 生成覆盖率数据后,重置之前的统计,想要重新获取统计数据,需要删除之前生成的exec文件
--address 运行jacocoagent.jar的主机IP
--port 运行jacocoagent.jar的主机监控端口
执行后,将在目录下生成指令中指定的 exec 文件 jacoco.exec
想要生成报告,需要同时指定源文件及编译后的字节码文件。
指定类文件及源代码路径,并生成格式为 html 的报告样式。
java -jar jacococli.jar report jacoco.exec --classfiles D:\Spring\JacocoTest\target\classes --sourcefiles D:\Spring\JacocoTest\src\main\java --html log
点击目录下的 index.html 将打开覆盖率信息
进入到测试类中,可以看到各方法的覆盖情况
进入到方法中,可以看到代码的覆盖情况。
绿色是完全覆盖,红色是未覆盖,黄色是部分覆盖。
想要获取全新覆盖率数据,需要删除步骤3中生成的 exec 文件,否则是累计覆盖率。
jacococli.jar 使用帮助
Usage: java -jar jacococli.jar report [] [--encoding ] [--help] [--html
] [--name ] [--quiet] [--sourcefiles ] [--tabwith ] [--xml ]
: list of JaCoCo *.exec files to read
--classfiles : location of Java class files
--csv : output file for the CSV report
--encoding : source file encoding (by default platform encoding is
used)
--help : show help
--html
--name : name used for this report
--quiet : suppress all output on stdout
--sourcefiles : location of the source files
--tabwith : tab stop width for the source pages (default 4)
--xml : output file for the XML report