代码覆盖率统计 Jacoco 技术
一、代码覆盖率统计的作用
1.1 面试题:你如何保障测试工作的质量?
常规方式:
- 根据需求文档里面写的功能需求,设计测试用例
- 用例评审 - 确保测试用例尽量覆盖到了这些功能
问题:
- 管理角度问题 - 测试人员是否执行了这些用例?
- 开发偷偷改动了代码
需要一个 客观的凭据(考核/数据)保障功能是不是测试到位?
解决方案思路来源:
- 功能都是由代码实现的,触发之后,代码运行实现了这个效果。
- 如果能够监控到测试过程中哪些代码被运行了,哪些代码没运行
1.2 什么是测试代码的覆盖率?
为什么它能够代表质量的客观数据:
- 系统功能是由开发人员编写代码实现
- 测试用例执行模拟用户去使用系统,触发代码的执行
代码覆盖率:统计哪些代码被执行了
举例: 开发写了100行代码,测试人员执行的系统测试之后,统计代码覆盖率:80%
意义: 100行代码,80行代码被触发执行了,20行代码没被执行。可能出现的原因:
- 开发人员代码有很多没用垃圾代码(提高了软件系统的维护难度,低质量的表现)
- 测试人员对于功能的使用没有覆盖到位(没触发对应的功能代表用例不到位)
二、Jacoco 框架工具介绍
JAVA本身没有代码覆盖率统计功能,难点:如何去统计这个代码有没有被执行呢?
2.1 Jacoco 框架是什么
Jacoco 是面向 Java 的开源代码覆盖率工具,Jacoco 以 java 代理模式运行,它负责在运行测试时检测字节码。Jacoco 会深入研究每个指令,并显示每个测试过程中要执行的行,为了收集覆盖率数据,Jacoco 使用ASM 即时进行代码检测,并在此过程中从 JVM Tool Interface 接收事件,最终生成代码覆盖率报告。
Jacoco 的运行模型有两种:
- 离线(offline):编译时插桩,在测试前先对文件进行插桩,然后生成插过桩的 class 或 jar 包,测试插过桩的 class 和 jar 包后,会生成动态覆盖信息到文件,最后统一对覆盖信息进行处理,并生成报告。
- 在线(on the fly):在线模式就是在应用启动时加入 jacoco agent 进行插桩,在开发、测试人员使用应用期间实时地进行代码覆盖率分析。
2.2 Jacoco 安装教程
- 准备JDK,在本机输入:
java --version确定是否显示对应的版本 - 下载 Jacoco,官网:https://www.jacoco.org/jacoco/ 【本教程使用的
0.8.8版本进行演示】 - 下载解压之后就可以进行使用
三、Jacoco 代码覆盖率项目实战应用
3.1 Jacoco 的使用场景
场景1:偏白盒测试 - 支持单元测试代码覆盖率统计
- 开发自测
- 白盒测试
- 开发人员编写单元测试代码
场景2:偏黑盒测试 - 代码覆盖率统计
- 针对于测试人员
- 手工测试或者自动化测试,执行完毕,可以通过工具看到代码覆盖率
覆盖率颜色说明:绿色-执行过;红色-未执行;黄色-分支部分执行。
3.2 项目实操演练
前提条件:
- 了解一些代码的概念,能够看懂一些代码更好。
- Java项目为例,你自己有一个可运行的 JAVA项目
- 借助 Jacoco 去分析代码覆盖率
第一步:启动应用
正常情况下,通过目前最主流 springboot 应用程序启动方式:java -jar 项目.jar 进行启动。
注意: 这个方法不可行,JAVA本身没有提供代码统计的功能。所以我们需要在启动java程序的时候,添加jvm的配置参数,给当前程序额外增加代码统计功能。
第二步:添加 jvm 配置参数
# 添加jacoco统计能力(jacoco解压之后 lib文件夹里面 jacocoagent.jar)
java -javaagent:/temp/jacocoagent.jar=includes=com.java2nb.*,output=tcpserver,port=6300,address=192.168.1.42,append=true -jar 项目.jar参数指定如下:
- Java Agent:启动时加载Java Agent以实现字节码修改、监控等功能
- javaagent:jacocoagent.jar路径,在jacoco的lib目录,比如:
\jacoco-0.8.8\lib - includes:你要统计的java代码包有哪些(项目代码 + 第三方库/模块)
- output:代码覆盖率统计的结果数据以什么形式导出(tcpserver)
- port、address:访问什么IP端口,去获取统计数据
示例命令:
java -javaagent:./jacoco-0.8.8/lib/jacocoagent.jar=includes=com.java2nb.*,output=tcpserver,port=6300,address=192.168.1.4,append=true -jar api-project.jar第三步:分析执行数据
根据埋点的数据,进行覆盖率分析
场景: A 测试人员针对注册功能设计了如下用例:
输入正确的手机号,及密码,及验证码,测试是否注册成功
输入重复的手机号,及密码,及验证码,测试是否提示重复注册
执行用例之后,0 BUG,测试通过
通过 jacoco 代码覆盖分析测试用例及用例执行是否覆盖到位
# 特定的jacoco客户端去获取项目中的代码执行数据
java -jar /temp/jacococli.jar dump --address IP地址 --port 端口号 --destfile ./jacoco_tcp_01.exec参考示例:
java -jar ./jacoco-0.8.8/lib/jacococli.jar dump --address 192.168.1.4 --port 6300 --destfile ./jacoco_tcp_01.exec- 把数据变成一个 html 可视化报告
java -jar /temp/jacococli.jar report ./jacoco_tcp_01.exec --sourcefiles D:\work\course\test\project\项目\src\main\java --classfiles D:\work\course\test\project\项目\target\classes --html ./report_test --encoding utf-8覆盖率报告结合源码进行展现,需要项目源码。
没测试到位的情况:根据覆盖率统计,反向分析到某些代码分支没测到,增加用例。
问题:代码被执行过,就代表测试用例完善?
- 否定。如果代码没被触发,覆盖率很低,一定代表系统测试有些功能没测试到。
- 如果代码覆盖率很高,不代表测试用例完善。
总结
QA 质量体系:所有的测试技术都是为了提高质量的下限。测试的目的不是为了发现所有BUG。
