jacoco多版本报告合并

news2024/9/20 21:26:47

jacoco提供了一个merge命令可以给我方便的合并代码无变更时的报告,但是一旦代码发生变化,则无法通过jacoco进行直接合并,原因在《jacoco的多次代码提交merge分析》中已经说明,那么针对一次功能测试,势必会进行多轮,每一轮针对变更的数据进行覆盖率增量报告,这是没有什么问题的,但是对于一些需求可能需要展示整个测试的覆盖报告,怎么将变更类的报告也进行合并呢?这就是本文讨论的问题。

通过之前的博客,我们理解了一旦类发生变更,探针的顺序势必不同,进而无法进行合并,因为jacoco的探针数据只是存储了其顺序和是否被访问,我们无法直接将两个探针进行强制合并。网络上针对代码变更类报告合并的资料相对比较少,很多实现的方案是基于一个最终报告的裁剪,比如我第一的报告有一个a方法,他的覆盖行数是10,第二次他的覆盖行数是20,简单做了一个累加就决定了他的覆盖行数是30(这里指指令),这样明显的漏洞是我第二次的覆盖里面包含了第一次的几行,两者应该是取并集,但是jacoco的报告里有报告相关的数据,不会有具体某个指令的覆盖情况,所以基于这种方式合并报告误差率非常高。
所以我们只能在生成报告的阶段去干涉覆盖率的合并,那么我们必然要熟悉报告的生成过程
当我们去生成报告的时候,非常重要的一个文件是jacoco.exec文件,我们可以通过官方人提供的命令去简单查看一下其内容:

java -jar jacococli.jar execinfo jacoco.exec 

在这里插入图片描述
第一行是一个classid,在上一篇文章中有讲解过,第二个数据就是每个类探针的信息,第三个数据就是类名。我们再梳理下jacoco生成报告的过程
在这里插入图片描述
因为exec文件没有记录方法的信息,所以生成报告的阶段则是会基于class文件重新进行一次插桩,同时会把探针的访问信息也会恢复,这样jacoco再使用ASM遍历每个类每个方法的指令去收集指令的覆盖率,然后以此再一层层运算到行覆盖率,方法覆盖率,类覆盖率,包覆盖率等。
根据上图所示,我们想对相同全限定名的类进行合并,则需要再对指令覆盖率进行合并。
在此基础上我们首先要对jacoco的report源码有一定的了解。

jacoco的report源码分析

很多伙伴对jacoco的调试功能比较陌生,其实我们使用jacoco的单测就很方便进行代码调试,我们以report cli为入口

在这里插入图片描述
只需要在这里写我们自己的单测用例即可
在这里插入图片描述
我们以reportcli为入口,如上图所示,我们在report的时候,主要有三个方法

  1. 解析exec文件并合并探针(只能合并相同classId的类的探针)
  2. 根据class文件和探针信息获取覆盖数据
  3. 绘制报告,在源码上渲染覆盖信息
    第一个方法我们再merge源码分析里已经清晰讲解过,这里我们详细讲解下第二个方法(第三个方法用例变更代码打标签功能,有兴趣的小伙伴可以自行了解下)
    在这里插入图片描述
    如上图所示,该方法会遍历我们所有文件里的class文件,在此之前创建了一个CoverageBuilder对象,这个对象会贯穿我们整个报告计算并最终得到源码覆盖率信息
    在上文我们已经提到过,由于探针记录的信息非常有限,我们想要得到指令的覆盖率,只能在class基础上再一次进行插桩,这也是为什么classid一旦发生改变无法进行合并的原因,在找到每一个class文件后进行遍历解析
    在这里插入图片描述
    这里我们要关注一下createAnalyzingVisitor方法,他的主要作用是为每个class文件创建一个ClassVistor
    在这里插入图片描述
    核心功能来了,这里我们遍历class文件内的每个方法,然后进行了插桩,通过个InstructionsBuilder对象接受了指令的覆盖信息,指令覆盖信息是jacoco覆盖率最基础最原子的数据,后面的行覆盖率,类覆盖率都是基于指令覆盖率去计算的,所以我们想做不同版本类的覆盖率,需要去合并指令覆盖率,这里有一个核心问题是一旦类发生变更了,但是其中的没有变更的方法指令是否是一样的呢
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    通过对比两个字节码,我们清晰的可以看出,指令是完全一样的,除了行号,那么我们是否就可以以此作为我们的突破口呢?
    ASM在遍历方法的指令时得到的结果又是怎样的呢?我们找到了两个不同版本的统一类进行分析
    在这里插入图片描述
    在这里插入图片描述
    由于截图所限我们发现指令的key完全是一模一样的,只不过指令的value里面的line是不一样的,其实看到这里我们就很清晰的知道合并指令,只需要合并branchs和coveredBranches即可,难点在于我们怎么判断两个方法是否相等,怎么判断两个指令是否相等(指令有很多种类型),由于builder对象存储的指令信息是map结果,无需的,无疑给我们的判断指令相等带了了更加复杂的挑战,就像上图所示的。如果是fieldInsnNode的指令类型,我们则需要判断操作码,onwe,name,desc等是否相等,如果是VarInsNode的指令,则需要判断操作码和var是否相等。

合并思路

  1. 引入历史版本的class文件

由于需要解析方法指令覆盖率,我们在原有的基础上需要引入历史版本的class文件

    @Option(name = "--oldClassfiles", usage = "location of old Java class files", metaVar = "<path>")
    List<File> oldclassfiles = new ArrayList<File>();
  1. 过滤历史版本的class文件
    拿到历史版本的class文件后,我们则需要对classs文件进行过滤,因为一个工程的class文件会特别多,这里我们可以采取使用executionData的classId进行过滤,没有覆盖率的类没有必要进入后续的计算。
  2. 先对历史版本的class文件进行插桩和指令覆盖率计算,然后将结果存储到一个map中
   //历史版本指令覆盖率,key为方法签名,value为指令覆盖率
    private Map<String, List<Map<AbstractInsnNode, Instruction>>> oldClassInstructionsMap = new HashMap<>();

需要注意的是我们只需要拿到历史版本的指令覆盖率,不需要进行后续逻辑,所以一旦获取到指令后中断
4. 进行当前版本正常的覆盖率计算,当发现存在oldClassInstructionsMap是进行指令合并
指令合并的思路是保证指令的唯一性,这样做方法变动版本和指令合并就会带来更加方便的操作,这里给每个指令加上一个签名

 

/**
 * 指令标志
 */
private String instructionSign;

在这里插入图片描述
在记录指令信息的时候将指令标识也维护进去,这样就能拿到每个指令的唯一标识了

    public Instruction merge(final Instruction other) {
        final Instruction result = new Instruction(this.line);
        result.branches = this.branches;
        result.coveredBranches.or(this.coveredBranches);
        result.coveredBranches.or(other.coveredBranches);
        result.instructionSign= this.instructionSign;
        return result;
    }

对于指令合并jacoco本身提供了一个这样的方法

最终效果如下,我们第一个版本做了一个全量的覆盖,第二个版本删除了test3,新增了test4,但是只副高绿test2和test4方法,我们合并报告后则会把之前test1的报告进行合并,最终得到一个全量的覆盖结果,指令覆盖结果也是没有出错的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

到此我们的多版本class报告合并就完成了,思路其实不麻烦,重点是了解jacoco在生成报告的逻辑,然后进行改造就可以了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/835396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C语言进阶(1)】数据存储

文章目录 Ⅰ 数据类型介绍⒈类型的基本分类 Ⅱ 整形在内存中的存储⒈原码、反码、补码⒉大小端介绍及判断大小端 Ⅲ 浮点型在内存中的存储⒈浮点数在内存中的存储规则⒉IEEE 754 对 M 和 E 的存取规定⒊解释前面的题目 Ⅰ 数据类型介绍 基本内置类型 类型类型名称char字符数据…

玄子Share - Mybatis 项目模板使用指南

玄子Share - Mybatis 项目模板使用指南 项目结构图 mybatis-config.xml 配置模板设置 参数 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.…

pycharm运行pytest无法实时输出信息

需要去掉控制台输出。根据查询相关信息显示pycharm运行pytest无法实时输出信息&#xff0c;需要去掉pycharm里面的运行模式&#xff0c;点击减号&#xff0c;再点击加号&#xff0c;添加python执行文件即可实时输出信息。 问题描述&#xff1a; 使用pycharm运行代码时&#x…

24考研数据结构-树与森林

目录 5.4树、森林5.4.1树的存储结构1. 双亲表示法(顺序存储)&#xff1a;2. 孩子表示法(顺序链式)3. 孩子兄弟表示法&#xff08;链式&#xff09; 5.4.2树、森林与二叉树的转换5.4.3树、森林的遍历1. 树的遍历先根遍历后根遍历层序遍历&#xff08;队列实现&#xff09; 2. 森…

LeetCode-26-删除有序数组中的重复项

一&#xff1a;题目描述&#xff1a; 给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯…

AI相机“妙鸭相机”原理分析和手动实现方案

妙鸭相机 一个通过上传大约20张照片&#xff0c;生成专属自拍。在2023年7月末爆火&#xff0c;根据36Kr报道&#xff0c;妙鸭相机系阿里系产品&#xff0c;挂靠在阿里大文娱体系下&#xff0c;并非独立公司。 使用方法是上传20张自拍照片&#xff0c;之后可以选择模板生成自己…

神码ai火车头标题伪原创【php源码】

这篇文章主要介绍了如何把python 代码打包成可执行软件&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 火车头采集ai伪原创插件截图&#xff1a; Python 程序封装-打包成exe程…

以指标驱动,保险、零售、制造企业开启精益敏捷运营的新范式

近日&#xff0c;以“释放数智生产力”为主题的 Kyligence 用户大会在上海前滩香格里拉大酒店成功举行。大会包含上午的主论坛和下午的 4 场平行论坛&#xff0c;并举办了闭门会议、Open Day 等活动。来自金融、零售、制造、医药等行业的客户及合作伙伴带来了超过 23 场主题演讲…

CSS调色网有哪些

本文章转载于湖南五车教育&#xff0c;仅用于学习和讨论&#xff0c;如有侵权请联系 1、https://webgradients.com/ Wbgradients 是一个在线调整渐变色的网站 &#xff0c;可以根据你想要的调整效果&#xff0c;同时支持复制 CSS 代码&#xff0c;可以更好的与开发对接。 Wbg…

selenium 截屏

当前环境&#xff1a; Windows 10 Python 3.7 selenium 3.141.0 Google Chrome 115.0.5790.110 &#xff08;64 位&#xff09; from selenium import webdriver import base64if __name__ __main__:#driver webdriver.Chrome()driver.get(https://www.baidu.com/)# 1.…

服务端高并发分布式结构演进之路

目录 一、常见概念 1.1基本概念 二、架构演进 2.1单机架构 2.2应用数据分离架构 2.3应用服务集群架构 2.4读写分离 / 主从分离架构 2.5引入缓存 —— 冷热分离架构 2.6垂直分库 2.7业务拆分 —— 微服务 一、常见概念 1.1基本概念 应用&#xff08;Application&am…

powerdesigner各种字体设置;preview字体设置;sql字体设置

1.设置左侧菜单&#xff1a; 步骤如下&#xff1a; tools —> general options —> fonts —> defalut UI font ,选择字体样式及大小即可&#xff0c;同下图。 2.设置preview字体大小&#xff08;sql预览&#xff09; 步骤如下&#xff1a; tools —> general o…

问道管理:两市股指冲高回落,沪指一度突破3300点,券商、保险板块领涨

8月4日&#xff0c;两市股指高开高走&#xff0c;沪指一度突破3300点。开盘后&#xff0c;沪指、深成指涨近1%&#xff0c;创业板指、上证50指数涨幅超1%。职业方面&#xff0c;券商、稳妥板块领涨&#xff0c;传媒、石油、半导体、银行、煤炭等板块均上扬&#xff0c;互联金融…

Oracle锁的学习

Oracle数据库中的锁机制 数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时&#xff0c;在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据&#xff0c;破坏数据库的一致性。 在数据库中有两种基本的锁类…

拓展商业视野:利用企业变更记录 API 剖析企业策略与决策

引言 随着商业竞争日益激烈&#xff0c;企业的战略与决策成为成功与否的关键因素。在这样的背景下&#xff0c;利用变更记录查询API成为了企业洞察竞争对手、揭示市场动态、发现商业机会的重要工具。本文将深入探讨变更记录查询API的应用&#xff0c;揭示它如何拓展商业视野&a…

【项目 进程14】2.30 守护进程(1) 2.31 守护进程(2)

文章目录 2.30 守护进程&#xff08;1&#xff09;终端进程组会话进程组、会话、控制终端之间的关系进程组、会话操作函数守护进程2.31 守护进程&#xff08;2&#xff09;守护进程的创建步骤写一个守护进程&#xff0c;每隔2s获取一下系统时间&#xff0c;将这个时间写入到磁盘…

【枚举+trie+dfs】CF514 C

Problem - 514C - Codeforces 题意&#xff1a; 思路&#xff1a; 其实是trie上dfs的板题 先把字符串插入到字典树中 对于每次询问&#xff0c;都去字典树上dfs 注意到字符集只有3&#xff0c;因此如果发现有不同的字符&#xff0c;去枚举新的字符 Code&#xff1a; #in…

会用这个医疗小技巧,升职加薪不加班!

在医药领域&#xff0c;温湿度监控是确保药品质量和安全性的重要环节。药品的生产、存储、运输和展示过程中&#xff0c;温湿度变化可能对药品的有效性产生不良影响&#xff0c;因此需要实时监测和管理环境条件。 通过有效的温湿度监控系统&#xff0c;医药企业和医疗机构能够确…

docker系列--解决hyper-v导致docker无法启动问题

一、问题 windows docker desktop 启动报错异常&#xff0c;导致docker无法启动成功 我们看到问题出在hyper-v的问题上&#xff0c;搜索解决方法&#xff0c;官网常见问题如下 Overview | Docker Documentation 二、解决 Hyper-V 已安装并正常工作 在BIOS中启用虚拟化 Wind…

mapstruct 错误 java.lang.NoSuchMethodError: Ljava/lang/Double 错误

问题描述 在使用 mapstruct 的过程中遇到错误 java.lang.NoSuchMethodError: Ljava/lang/Double 错误 问题解决 maven clean, 然后 maven install Build -> Rebuild Project 执行 maven install 时, 如果报错 找不到 xxx 类, 但 ctrl鼠标左键 发现可以点进去这个类, 那…