移动端精准测试之跨版本覆盖率合并

一,项目简介

     在移动端项目测试过程中,尤其是发版前的回归测试阶段,会遇到这样的情况,在测试过程中测试不断地发现问题,开发就进行修改,然后打包测试。而测试完成后呢,业务测试同学想知道整个回归测试阶段的覆盖率情况,但是针对每次不同的打包,会根据对应的版本生成相应的报告,不同版本的覆盖率执行如何进行合并呢?

       在网上搜索了一下,jacoco本身有jacoco merge功能,但是只针对同一版本的,如果版本变化了,也就意味着类有变化,那这个类在老版本中所有的覆盖率数据就会被丢掉。这样一来,必须会丢失一些版本中的覆盖率数据,同时,如果函数有变化,则这个函数调用链路上的所有功能就要重新测试,原来的覆盖率数据就要丢弃。综合考虑,无法直接使用jacoco merge来进行跨版本的覆盖率数据合并,这就要求我们自己开发一套覆盖率合并方案。

二,覆盖率合并方案介绍

1,网上方案调研  

 通过调研网上现有的jacoco覆盖率合并方案,得到了一些思路,但是没有切实可行的方案。参考文档:

  • 基于 Jacoco 的二次开发【解决不同版本 exec 数据合并问题】:

    https://testerhome.com/topics/30776

  • jacoco的多次代码提交merge分析:

    https://chowdera.com/2022/195/202207130538134324.html

  • 写给android同学的代码覆盖率讲解:

    https://www.jianshu.com/p/97caec282998

  • JaCoCo探针策略原理及案例总结:

    https://bbs.huaweicloud.com/blogs/274224

2,自研合并方案

     针对业务同学的要求,需要对同一分支不同版本的多次打包产生的覆盖率数据进行合并,不同分支的合并起来意义不大。但合并过程中也涉及到众多处理逻辑,现在将整体方案流程介绍如下:

图片

介绍:

1,对比要合并的版本,先按版本合并覆盖率数据文件,找出diff的函数列表;

2,通过diff函数列表,查询调用链路,找到其影响的上游函数列表,组成受影响的函数列表。

3,对受影响的函数列表,找到其在老版本中的行号,去掉对应的行号的覆盖率信息。

4,根据diff函数列表,找到其所在类中的位置没有变化的函数列表,以及位置变化的函数列表。

5,针对位置没有变化的函数列表,将旧版本中的覆盖率信息,写入到合并后的覆盖率文件中;

6,针对位置有变化的函数列表,将旧版本中的覆盖行号校正为新版本中类的对应的行号,写回覆盖率文件中。

7,循环处理所有需要合并的版本覆盖率数据文件,生成最终的覆盖率文件。

三,Android 跨版本覆盖率合并

  针对Android系统的跨版本覆盖率合并,diff函数可以通过git提供的功能来实现,查询类中函数的起始位置,由主站的同学提供的解析kotlin和java文件的功能来解析。而最重要的就是,对覆盖率数据文件EC的处理。主站同学提供的jacoco-parser.jar工具,用来解析覆盖率ec文件覆盖的行号,而无法修改EC文件,而我们的需要对EC文件进行处理。

1,EC文件的处理

图片

    这样的处理没有办法直接通过java代码或是python来处理,只能开发一个单独的工具,来操作EC文件。所以就优化了主站同学的jacoco-parser.jar,引用jacoco插件来处理EC文件,最终生成的工具是jacoco-parser2.0.jar.

2,版本合并时函数处理

合并版本的时候,需要处理的函数信息有如下几类:

  • diff函数及其在调用链路中影响到的函数列表;

  • diff函数所在类,位置没有变化的函数列表;

  • diff函数所在类,位置有变化,需要在新版本中修正行号的函数列表。

具体的处理流程如下:

图片

为了与先前的覆盖率生成功能保持一致,节省相关操作,故将此功能放到了Android  Agent上,以服务的形式对精准测试平台提供服务。

3,精准测试平台合并覆盖率

      为了让测试同学来合并覆盖率操作,需要在精准测试平台上添加合并覆盖率的操作,通过精准测试平台向Agent发送消息,同时借助于原来的生成覆盖率报告的逻辑生成最终的合并后的覆盖率报告。最终的流程如下所示:

图片

    当得到了合并后的最终all-merged.ec文件后,就可以根据项目的其他信息,如当前分支,对比分支,最新的构建号等生成合并后的全量及增量覆盖率报告。

四,iOS 跨版本覆盖率合并

    iOS端的覆盖率合并,相对于Android端容易一些,因为iOS生成报告之前,会生成一个info文件,处理这个文件比EC文件简单多了。整体合并方案就是对比两个版本的info文件,根据diff函数列表,位置变化的函数列表进行处理。

1,iOS跨版本合并流程

图片

    通过上面的处理,以及对比合并后的覆盖率报告,发现一个问题:合并后的覆盖率报告行覆盖率没有问题,但是方法覆盖率不正确,也是不能直接对数据进行处理的。需要一定的逻辑处理才行,经过调研后,可以从下面的方式来进行。

2,iOS Swift跨版本覆盖率合并方法合并

图片

目前的功能暂时不对覆盖率合并后的文件进行校正的,根据业务同学在使用过程中,是否需要这个指标,如果需要,在Agent上添加相应的功能即可。

其中的合并两个info文件的操作,是自研的代码来处理的,主要思路是:

  • 先以最新的版本的info文件为基础,分别使用sed获取其中的文件以覆盖率信息;

  • 再从旧的版本的info文件中,找到相应的文件的覆盖率信息;

  • 按不同的情况,如新文件中有,旧的文件中没有;旧的文件中有,新的文件中没有;两个文件中都有,进行合并行覆盖率数据;

  • 最后将合并后的info文件写入新文件,再拷贝成较大的版本的文件,循环合并所有版本;

这种方法没有错误,但是当info文件中的文件信息过多时,如60多万行数据时,速度就非常慢,差不多要一个多小时才行。

有什么办法可以优化一下吗?

1,通过在网上搜索相关资料,找到lcov的使用文档:https://blog.csdn.net/qq_36614557/article/details/120264262

文档中说可以使用-a参数 合并两个lcov生成的文件,如下所示:

图片

2,通过两次详细搜索,合并方法如下

lcov -a test1.info -a test2.info -o allreport.info

经过验证,合并结果达到了预期,而合并速度快的不是一个数据级,非常开心!

3,在生成iOS覆盖率报告是,生成的info文件命令

xcrun llvm-cov export "+procpath+"Kima --instr-profile="+procpath+"coverage_merged.profdata -use-color --format=lcov > "+procpath+"allreport_"+commitid+".info"

完全符合要求。

 于是合并info文件的函数变成如下所示,比原来的简单了太多了:


def newMergeTwoInfoFile(self,srcinfofile,destinfofile):"""使用llcov -a 合并(归并)多个lcov生成的info文件:param srcinfofile::param destinfofile::return:"""newinfofile=destinfofile[0:destinfofile.rindex("/")+1]+"merged_report.info"if os.path.exists(srcinfofile) and os.path.exists(destinfofile):mergecmd=self.lcovcmd+" -a "+srcinfofile+" -a "+destinfofile+" -o "+newinfofileos.system(mergecmd)#将删除过覆盖率数据的info文件,更名为老的文件rmcmd="rm -rf "+destinfofileos.system(rmcmd)mvcmd="mv "+newinfofile+" "+destinfofileos.system(mvcmd)else:print("要合并的两个info文件:"+srcinfofile+","+destinfofile+"不存在!")

最终的合并覆盖率报告执行时间,也由原来的一个小时二十多分钟,降低到了二十多分钟!

3,精准测试平台iOS覆盖率合并方案

图片

     由于在容器上无法处理iOS覆盖率报告,所以只能根据keep构建号把覆盖率数据文件profraw上传到Agent上来处理。iOS Agent需要做大量对覆盖率数据处理,生成info文件,合并info文件的操作。其中对函数的过滤和处理使用的是经过二次开发的工具drafter,这个工具可以根据文件来返回文件中的函数列表,包括起始位置。

五,总结

覆盖率跨版本合并,正常情况下是不允许的,这也是为什么jacoco就不支持的原因。因为类一旦变化了,类中函数的位置,函数内容都会变化,同时其调用函数也会受到影响。极端的情况,就是函数中的逻辑变化了,先前与这个函数相关的所有操作都要重新测试。

1,Android中的覆盖率数据是通过探针来控制覆盖情况的,如果多个探针同时控制一个覆盖逻辑的话,上面的覆盖率行号的修改就会出错;由于探针和行号不是一一对应的,所以很难根据探针准确地修改行号的覆盖情况。现在的合并方案虽然比直接jacoco merge更加准确一些,但是也不完全准确。

2,iOS覆盖率的合并,其实是对Info文件做了处理,针对覆盖的行号的后面的数字做了处理,如原行号覆盖为0,改成1还好理解。如果原来行号覆盖数据是2,要合并的是3,合并后改成了5。这个5在报告中如何渲染的呢?其实没有太搞明白。现在info文件信息解读,网上也不多。

六,常见问题

     在实际使用过程中,增加了对项目Module模块的覆盖率的收集,生成的测试报告显然比原来的更加全面了,但出现了两个问题:

1,覆盖率收集的Pod相关的文件,生成报告的时候找不到文件?

      由于项目和Module的调用,会出现一些Pod中的头文件信息,这是因为主代码与pod module交互的接口或是过度等。但是生成覆盖率报告的时候,在源项目中是找不到对应的文件的,所以genhtml报告时会因文件找不到出错。

解决方案:在生成覆盖率报告info文件后,过滤掉info文件中与pod相关的文件及其覆盖率信息,以保证生成html报告时不会出错文件找不到的问题。

2,iOS覆盖率合并的时候,合并版本与项目分支对应的版本不同,会出现文件找不到?

      在进行覆盖率的合并的时候,由于创建覆盖率任务与生成报告时间间隔内,如果开发有提交代码,早期的更新项目的逻辑是拉出对应分支最新 的版本,可能造成新版本修改了文件,老版本的覆盖率报告找不到文件。

解决方案:在生成合并覆盖率合并报告时,先获取要合并覆盖率报告任务的最新版本号,将项目切到这个版本再生成报告。生成完成后,再切回分支的最新版本,防止影响其他的操作。

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

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

相关文章

Qt 5.14.2 网络编程揭秘:构建高效HTTP客户端与文件下载器

引言 在当今的软件开发世界中,网络通信已成为不可或缺的一部分。Qt,作为一个跨平台的C框架,为我们提供了强大的网络编程能力。本文将带你深入Qt的网络模块,探索如何使用QNetworkAccessManager、QNetworkRequest和QNetworkReply等核…

【HarmonyOS】ArkTS-对象方法

目录 对象方法实例 对象方法 方法作用:描述对象的具体行为 约定方法类型 interface 接口名称 { 方法名: (参数:类型) > 返回值类型 }interface Person{dance: () > voidsing: (song: string) > void}添加方法(箭头函数) let ym: P…

电商数据分析18——电商广告投放的数据分析与优化

目录 写在开头1. 电商广告投放的挑战与机遇1.1 广告投放的主要目标与挑战1.2 广告数据分析的价值 2. 数据分析在广告投放中的应用2.1 目标受众分析与精准定位2.2 广告效果评估与ROI分析2.3 A/B测试与广告内容优化 3. 广告投放优化的实践案例3.1 案例分享:精准定向提…

springboot使用EasyExcel实现Excel导入导出

java生成Excel比较有名的框架有Apache poi、jxl等,但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。 EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。…

微前端之再说无界的使用

运行模式 保活模式单例模式重建模式 生命周期改造 改造入口函数: 应用间通信 原理props 通信 主应用可以通过 props 注入数据和方法:子应用可以通过 $wujie 对象来获取数据: window 通信 主应用调用子应用的全局数据:子应用调用主…

每天学习一个Linux命令之find

每天学习一个Linux命令之find 概述 在Linux系统中,find命令是一个非常强大的工具,用于查找和操作文件和目录。它可以根据一些条件来搜索指定路径下的文件,并执行相应的操作。本篇博客将详细介绍find命令的各个可用选项及其用法。 基本语法…

lvs集群中NAT模式

群集的含义 由多台主机构成,但对外表现为一个整体,只提供一个访问入口,相当于一台大型的计算机。 横向发展:放更多的服务器,有调度分配的问题。 垂直发展:升级单机的硬件设备,提高单个服务器自身功能。 …

如何保证消息不丢之MQ重试机制消息队列

1. 简介 死信队列,简称:DLX,Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另外一个交换机,这个交换机就是DLX 那么什么情况下会成为Dead message&a…

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文:https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译:OneBlock 区块链领域不断发展,随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

深入理解nginx一致性哈希负载均衡模块[上]

1. 引言 在现代的网络应用中,负载均衡是一个至关重要的组件。它能够分配流量到多个服务器上,实现高可用性和性能扩展。Nginx是一个广泛使用的高性能Web服务器和反向代理服务器,其负载均衡模块提供了多种算法来实现流量的分发。其中&#xff0…

【刷题记录】详谈设计循环队列

下题目为个人的刷题记录,在本节博客中我将详细谈论设计循环队列的思路,并给出代码,有需要借鉴即可。 题目:LINK 循环队列是线性表吗?或者说循环队列是线性结构吗? 对于这个问题,我们来看一下线…

【Linux进阶之路】网络 —— “?“ (下)

文章目录 前言一、概念铺垫1.TCP2.全双工 二、网络版本计算器1. 原理简要2. 实现框架&&代码2.1 封装socket2.2 客户端与服务端2.3 封装与解包2.4 请求与响应2.5 对数据进行处理2.6 主程序逻辑 3.Json的简单使用 总结尾序 前言 在上文我们学习使用套接字的相关接口进行了…

面试经典150题(108-110)

leetcode 150道题 计划花两个月时候刷完之未完成后转,今天(第3天)完成了3道(108-110)150 108.(201. 数字范围按位与) 题目描述: 给你两个整数 left 和 right ,表示区间 [left, right] ,返回此区间内所有数…

Tomcat的安装

下载Tomcat(这里以Tomcat8.5为例) 直接进入官网进行下载,Tomcat官网 选择需要下载的版本,点击下载这里一定要注意:下载路径一定要记住,并且路径中尽量不要有中文!!!&…

怎么把视频变成gif动图?一招在线生成gif动画

MP4是一种常见的视频文件格式,它是一种数字多媒体容器格式,可以用于存储视频、音频和字幕等多种媒体数据。MP4格式通常用于在计算机、移动设备和互联网上播放和共享视频内容。要将MP4视频转换为GIF格式,您可以使用专门的视频转gif工具。这个工…

三款顶级开源RAG (检索增强生成)工具:Verba、Unstructured 和 Neum

三款顶级开源RAG (检索增强生成)工具:Verba、Unstructured 和 Neum 概述 随着企业对话式数据处理需求的提升,面临的挑战是数据隐私性和缺乏企业级解决方案。虽然类似LangChain能在短时间内构建RAG应用,但忽视了文档解析、多来源数据ETL、批量…

Python 对Excel工作表中的数据进行排序

在Excel中,排序是整理数据的一种重要方式,它可以让你更好地理解数据,并为进一步的分析和报告做好准备。本文将介绍如何使用第三方库Spire.XLS for Python通过Python来对Excel中的数据进行排序。包含以下三种排序方法示例: 按数值…

【洛谷 P8723】[蓝桥杯 2020 省 AB3] 乘法表 题解(数学+进制转换+字符串)

[蓝桥杯 2020 省 AB3] 乘法表 题目描述 九九乘法表是学习乘法时必须要掌握的。在不同进制数下,需要不同的乘法表。 例如, 四进制下的乘法表如下所示: 1*11 2*12 2*210 3*13 3*212 3*321请注意,乘法表中两个数相乘的顺序必须为样例中所示的…

从0开始的 Vue 生活

Vue 一、配置环境1.1 安装node.js1.1.1 node.js 下载1.1.2 node.js 安装1.1.3 node.js 配置 1.2 安装VSCode1.2.1 VSCode 下载1.2.2 VSCode 安装1.2.3 VSCode 配置 二、创建Vue项目2.1 使用命令行创建Vue项目2.2 使用VSCode运行Vue项目2.3 尝试编写Vue项目2.3.1 准备工作2.3.2 …

线性代数笔记14--投影

1. 一维空间投影 p X A e B − p B − X A A ⊤ e 0 A ⊤ ( B − X A ) 0 X A ⊤ A A ⊤ B X A ⊤ B A ⊤ A p X A A A ⊤ B A ⊤ A pXA\\ eB-pB-XA\\ A^{\top}e0\\ A^{\top}(B-XA)0\\ XA^{\top}AA^{\top}B\\ X\frac{A^{\top}B}{A^{\top}A}\\ pXAA\frac{A^{\top}B}{A^…