公司突然要求自动化测试对代码的覆盖率,故研究了一波jacoco相关
现状
- 要拉取的是接口自动化测试的覆盖率,非单元测试的,所以本身必须是在服务部署通过的情况下进行覆盖率的收集
- 我们这使用的是容器,java springboot的框架
agent官网去学习了一波
调研了一波
- ant和maven的方法都是在编译过程中单元测试时出分辨率
- jacoco agent是在服务启动后,收集代码覆盖率
其实实际使用并不难,主要是在springboot的启动命令里面加入javaagent的参数配置,官方提供了2种方案(tcpclient没看到外面有人使用 故先忽略)
- output=file
- 在每次服务结束时统一收集覆盖率dump
- java -javaagent:/tmp/jacoco/lib/jacocoagent.jar=includes=*,output=file,append=true,destfile=/tmp/jacoco/service/demo/jacoco.exec -jar demo-0.0.1-SNAPSHOT.jar
- output=tcpserver
- 开放一个tcp端口,可以在过程中收集覆盖率dump
- java -javaagent:/tmp/jacoco/lib/jacocoagent.jar=includes=*,output=tcpserver,port=6300,address=localhost,append=true -jar demo-0.0.1-SNAPSHOT.jar
- 需要通过jacococli.jar 来获取dump
- java -jar jacococli.jar dump --address localhost --port 6300 --destfile ./jacoco-demo.exec
- -javaagent
jdk5之后新增的参数,主要用来在运行jar包的时候,以一种方式介入字节码加载过程,如有兴趣自行百度。注意后面有个冒号: - /home/admin/jacoco/jacocoagent.jar
需要用来介入class文件加载过程的jar包,想深入了解的,百度“插桩”哈。
这是一个jar包的绝对路径。 - includes=*
这个代表了,启动时需要进行字节码插桩的包过滤,*代表所有的class文件加载都需要进行插桩。
假如你们公司内部代码都有相同的包前缀:com.mycompany
你可以写成:
includes=com.mycompany.*
- output=tcpserver
这个地方不用改动,代表以tcpserver方式启动应用并进行插桩 - port=2014
这是jacoco开启的tcpserver的端口,请注意这个端口不能被占用 - address=192.168.110.1
这是对外开发的tcpserver的访问地址。可以配置127.0.0.1,也可以配置为实际访问ip
配置为127.0.0.1的时候,dump数据只能在这台服务器上进行dump,就不能通过远程方式dump数据。
配置为实际的ip地址的时候,就可以在任意一台机器上(前提是ip要通,不通都白瞎),通过ant xml或者api方式dump数据。
举个栗子:
我如上配置了192.168.110.1:2014作为jacoco的tcpserver启动服务,
那我可以在任意一台机器上进行数据的dump,比如在我本机windows上用api或者xml方式调用dump。
如果我配置了127.0.0.1:2014作为启动服务器,那么我只能在这台测试机上进行dump,其他的机器都无法连接到这个tcpserver进行dump。
获取出来的就是exec的dump文件,那么接下来就要生成报告了
官方又提供了2种方案,其他我
- ant转报告
- 开发工具直接展示
- jacococli.jar 转报告
ant本身需要安装环境,还要定制build.xml,个人比较懒,而且平时使用ant的机会也不多,所以没用这个方案
开发工具直接看结果可以(idea Analyze->Show Coverage Data->选择exec文件),但后续不利于做二次开发
jacococli.jar 本身有report方法是专门用来转报告的
java -jar jacococli.jar report ./jacoco-demo.exec --classfiles /Users/oukotoshuu/IdeaProjects/demo/target/classes/com --sourcefiles /Users/oukotoshuu/IdeaProjects/demo/src/main/java --html report --xml report.xml
经个人尝试:
--classfiles 必须项,是编译后target 文件夹下的classes里面的com
Jacoco 包含了多种尺度的覆盖率计数器,包含指令级(Instructions,C0 coverage),分支(Branches,C1 coverage)、圈复杂度(Cyclomatic Complexity)、行(Lines)、方法(Non-abstract Methods)、类(Classes)。
➢ Instructions:Jacoco 计算的最小单位就是字节码指令。指令覆盖率表明了在所有的指令中,
哪些被指令过以及哪些没有被执行。这项指数完全独立于源码格式并且在任何情况下有效,不需要类文件
的调试信息。
➢ Branches:Jacoco 对所有的 if 和 switch 指令计算了分支覆盖率。这项指标会统计所有的分支数
量,并同时支出哪些分支被执行,哪些分支没有被执行。这项指标也在任何情况都有效。异常处理不考虑在分支范围内。
➢ Cyclomatic Complexity:Jacoco 为每个非抽象方法计算圈复杂度,并也会计算每个类,包,组的复杂度。根据 McCabe1996 的定义,圈复杂度可以理解为覆盖所有的可能情况最少使用的测试用
例数。这项参数也在任何情况下有效。
➢ Lines:该项指数在有调试信息的情况下计算。
➢ Methods:每一个非抽象方法都至少有一条指令。若一个方法至少被执行了一条指令,就认为它被执行过。因为 JaCoco 直接对字节码进行操作,所以有些方法没有在源码显示(比如某些构造方法和由编
译器自动生成的方法)也会被计入在内。
➢ Classes:每个类中只要有一个方法被执行,这个类就被认定为被执行。同 5 一样,有些没有在源码声明的方法被执行,也认定该类被执行。
--sourcefiles 理论可以不传,不传的话 只能到文件级的展示,再细 需要具体代码和行数就需要这个了
--csv 这个维度只能到代码文件级 pass
--xml 这个就比较细致了适合目前的需求
接下来目标就是再实际过程中实施了,到时候看下坑有多大吧,后面根据这个为基础搞实时的代码覆盖率,长路漫漫 学习不止~