网站首页 > 教程文章 正文
前言
代码测试覆盖率是一种度量,它描述了对程序源代码的测试程度,是白盒测试的一种手段,能够直观暴露测试用例无法覆盖到的代码块。作为提升代码质量的利器,我们在如何接入、使用等方面做了一些探索性的尝试与实践。
01 背景
作为一个测试人员,保证产品的软件质量是其工作首要目标,为了这个目标,测试人员常常会通过很多手段或工具来加以保证,而覆盖率就是其中比较重要的一个环节。覆盖率是用来度量测试完整性的一个手段,是测试技术有效性的度量。希望有个平台可以统计整个迭代的后端覆盖率数据报告,包括接口测试、功能测试、自动化测试等。测试人员可以通过测试覆盖情况来分析自身测试质量,同时达到最终提升测试质量的目的。
但是覆盖率有一个致命的缺陷就是如果功能没有开发,你永远都不可能测试到对应的代码覆盖,当然这是一个不太现实的话题,需要开发测试对需求必须熟悉的前提下开展,覆盖率测试对测试辅助作用还是比较大的。
02 平台参考意义
1.协助测试人员完善测试用例及测试场景,具体表现为:
通过代码覆盖率报告可以明确,哪些代码是执行过的,哪些代码是没有执行过的。对于那些没有执行过的代码,测试人员就需要思考是否是代码逻辑设计问题还是测试用例问题。如果是代码逻辑问题,那么测试人员需要与开发人员和产品人员沟通,达成需求理解的一致性。如果是测试用例问题,那么需要补足缺失的测试用力场景,尽可能保证所有重要的场景都覆盖到了,避免未测试的代码上线造成应用服务故障。
2.减少无用代码,提升代码质量:
开发人员通过覆盖率报告可以获得代码的执行流程走向,帮助开发梳理理解代码,起到codereview的作用。同时通过分析生产环境的代码覆盖率报告,还可以区分出真实的用户请求执行覆盖情况,区分“有用/无用”代码,有利于优化简化代码逻辑,从而起到减少不必要的无用代码。
3.代码质量标准:
代码覆盖率是一个确切的数值,能够从一定意义上通过量化测试代码数据来基本衡量测试的充分性,将模糊定义的代码质量用精准的数据来量化,是白盒测试和代码质量的衡量指标。从代码覆盖率报告可以明确,哪些代码是执行过的,哪些代码是没有执行过的,从未执行过的代码可以推算出测试用例是否充足,帮助测试人员理清代码逻辑和完善测试用例。代码测试覆盖率作为一项衡量代码质量的重要标准,可以在测试阶段发现隐藏问题,将隐性问题消灭在上线前期,减少线上问题发生。
03 平台整体方案设计
系统集成全量代码覆盖率统计和增量代码覆盖率统计(可以基于Git commit id或者分支名称对比差异),基于Jacoco的On-The-Fly在线模式,通过系统定时统计覆盖率,或者QA手动触发统计操作。
基本流程如下:
平台设置基准分支和对照分支,同时触发代码覆盖率统计,通过对.exec文件分析,以及增量代码差异分析,获取全量和增量覆盖率统计报告。
功能模块图:
04 重点模块
我们的设计方案也是基于jacoco和superJacoco做相应的二次改造开发(感谢前辈们的努力),生成我们所需要的覆盖率模型,并通过jacoco开放的API实现相关功能。
- Code Coverage配置 录入需要统计的维度信息,包括:程序源代码Gitlab地址、统计的模块名称、基准和对比的版本、部署的服务器IP、java版本、选择统计的类型(全量或者增量)等;
- 核心计算程序扫描处于初始化状态的数据,执行数据计算操作;
- 克隆代码:根据配置的git地址克隆代码到本地(使用eclipse的JGit);
- 解析模块:解析源代码中pom.xml配置文件获取有效的模块(modules)列表,持久化入库;
- 编译代码:执行命令cd到源代码目录下,执行mvn clean compile编译代码并输入日志到log文件中;
- 解析差异代码并计算增量方法:基于JGit分析计算基准版本和对比版本之间的差异的文件(排除删除和单元测试的文件),筛选出所有以.java结尾的文件。如果文件为新增(ADD)则添加整个文件到增量方法;如果文件为修改(MODIFY),则分别计算基准分支和对比分支代码,将代码方法体计算md5,然后计算出对比分支相较于基准分支有修改的方法名称,持久化到数据库中;
- 拉取exec文件:遍历所有配置的项目机器地址,通过jacoco dump工具,从项目机器上拉取功能测试的执行轨迹.exec文件,更新到本地;
- 统计覆盖率报告:通过jacoco-cli工具计算覆盖率,如果增量方法不为空,在统计覆盖率时只统计增量方法,最终生成覆盖率报告。将结果持久化到数据库。
全量覆盖率处理逻辑:
- 获取到一个全量代码覆盖率的收集,我们把它拆分成了以下几个步骤去实施:获取测试完成后的 .exec 文件(二进制文件,里面有探针的覆盖执行信息, 记录了代码的覆盖情况);
- 获得本次部署的镜像,拿到插桩后的 classes;
- 获取基线提交的代码(本次部署的 gitlab 上对应 commit 的代码);
- 利用 jacoco 的 api 生成报告.
diff覆盖率处理逻辑:
在平时测试过程中,如果是需要看一个应用本次发布的代码和某一次发布的代码之间的差异点是否都已经测试到了,那么我们的关注点就不在于全量的覆盖情况,而是一个增量覆盖,也就是本次的代码和上一次的代码改动量的覆盖情况。我们可以通过改造上述三件套,来实现这样的需求。具体实施步骤如下:
- 获取测试完成后的 exec 文件(二进制文件,里面有探针的覆盖执行信息, 记录了代码的覆盖情况);
- 获得本次部署的镜像,拿到插桩后的 classes;
- 获取基线提交与被测提交之间的差异代码;
- 对差异代码进行解析,切割为更小的颗粒度,选择方法为最小维度;
- 改造 JaCoCo ,使它支持仅对差异代码生成覆盖率报告。
镜像打包插桩部署获取class文件处理逻辑:
获取.exec文件并Merge 我们获取 exec 文件是通过 tcp 方式获取的,在部署 java 应用服务时,指定了 -javaagent 参数的 output 为 tcpserver ,并指定可用端口,所以 javaagent 参数设定如下:output=tcpserver,address=0.0.0.0,port=xxxx,然后将 javaagent 参数注入 JVM ,注入成功后才能收集到我们想到的覆盖率数据。对于负载多台机器,先做单机各种情形下的merge再负载merger exec文件。
解析差异代码:
基于JGit分析计算基准版本和对比版本之间的差异的文件(排除删除和单元测试的文件),筛选出所有以.java结尾的文件,其中包含了差异代码的具体内容、行号、文件名等等信息。如果文件为新增(ADD)则添加整个文件到增量方法;如果文件为修改(MODIFY),则分别计算基准分支和对比分支代码,将代码方法体计算md5,然后计算出对比分支相较于基准分支有修改的方法名称,持久化到数据库中。
包含核心逻辑操作步骤为:
- 通过JGit对比文件之间的差异;
- 分析这些文件之间的差异;
- 遍历差异文件,并且筛选出所有以.java结尾的文件;
- 通过基准分支与对比分支的MD5列表,找出他们的差异;
- 生成统计报告。
通过jacoco-cli工具计算覆盖率,如果增量方法不为空,在统计覆盖率时只统计增量方法,最终生成覆盖率报告。将结果持久化到数据库。
05 效果
核心模块整体操作界面如下图:
报告指标
增量报告
包视图
类视图
方法视图
代码视图
报告详解
可视化的html覆盖率报表,协助覆盖情况精准分析,支撑精准测试落地。
序号 | 字段名称 | 名称 | 描述 |
1 | Element | 元素 | 最外层展示分组名称,依次为:包>类>方法 |
2 | Missed Instructions Cov. | 指令覆盖字节码中指令 | 1、Jacoco计算的最小单位就是字节码指令2、指令覆盖率表明了在所有的指令中,哪些被执行过以及哪些没有被执行。 |
3 | Missed Branches Cov. | 分支覆盖率 | 1、对所有的if和switch指令计算分支覆盖率2、用钻石表示 |
4 | Missed Cxty | 圈复杂度 | Jacoco为每个非抽象方法计算圈复杂度,并也会计算每个类,包,组的复杂度。根据McCabe1996的定义,圈复杂度可以理解为覆盖所有的可能情况最少使用的测试用例数。 |
5 | Missed Lines | 行 | 用背景色标识的都算行统计目标,变量定义不算行,else也不算 |
6 | Missed Methods | 方法 | 每一个非抽象方法都至少有一条指令,若一个方法至少被执行了一条指令,就认为它被执行过。 |
7 | Missed Classes | 类 | 每个类中只要有一个方法被执行,这个类就被认定为执行。 |
06 实现成果和实现细节
1、支持JDK8与JDK11所有代码;
2、简化&优化Jacoco报告统计指标,使报告指标贴合大众理解,为后续测试提供了一个测试完成后的量化测试报告依据,并且可以反推测试与开发;
3、支持负载均衡的覆盖报告的收集,以及同版本不同时期的测试覆盖率增量测试报告;
4、与传统测试手段对比测试透明度高,评估需求更加清晰,开发代码逻辑的清晰,测试完成的测试后代码测试覆盖率的量化
5、提供全局排除及核心功能覆盖设置功能
全局排除功能:是为了排除项目中的非业务代码或外部包等无用代码,免除计入覆盖率统计与展示.
核心功能覆盖设置功能:则是通过对项目代码进行分析,确定业务的核心功能涉及的类和方法有哪些,录入设置后便可只针对这些核心类方法进行覆盖率统计。
07 未来规划
1.和持续测试平台打通,结合精准测试的调用链分析功能,将覆盖粒度精确到函数级别,可以获得每条用例覆盖到的函数和影响到的接口,通过更小的维度更精准地度量测试质量;
2.通过覆盖率来推导测试系统上下游之间的影响链条;
3.做更多的定制化功能相关开发,特别是报告方面要处理无关代码对测试覆盖报告的影响。
4.解决lombok插件自动生成代码覆盖率报告的的隔离问题。
参考资料
https://github.com/didi/super-jacoco
https://www.jacoco.org/jacoco/trunk/doc/
转载自 https://mp.weixin.qq.com/s/fcj-dA1JxIfm3N1OBVlu2g
- 上一篇: Java关于代码质量度量和分析的一些总结
- 下一篇: 从0到1构建基于自身业务的前端工具库
猜你喜欢
- 2025-01-24 代码覆盖率VS测试覆盖率(代码覆盖率检查)
- 2025-01-24 嵌入式开发:ARM Cortex-M微控制器的5种调试技巧
- 2025-01-24 从0到1构建基于自身业务的前端工具库
- 2025-01-24 Java关于代码质量度量和分析的一些总结
- 2025-01-24 白盒测试怎么做(白盒测试的基本步骤)
- 2025-01-24 代码的圈复杂度(代码圈复杂度指什么)
- 2025-01-24 软件外包项目的功能测试(软件测试外包都是短期的吗)
- 2025-01-24 车载控制器软件MBD_MIL测试技术及要求(第二期)
- 2025-01-24 Python 标准库中鲜为人知的宝藏 | Node.js 22.8.0 发布
- 2025-01-24 1次订单系统迁移,头发都快掉完了...
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)