jacoco 代码覆盖率统计不上问题破解之谜
把从jenkins编译出的class(即应用打包的class)复制到覆盖率收集服务下,然后做代理通信,发现测试用例被统计到了,问题终于快找到了,应该是两次编译生成的class不一样。最近在搞jacoco代码覆盖率,已经集成在公司现有的devops平台里,但是在实际的使用过程中发现测试人员明明已经执行过的测试用例,有些class覆盖率统计却为0、有些能正常统计出来,到底是怎么回事呢?:为了防止命名冲
最近在搞jacoco代码覆盖率,已经集成在公司现有的devops平台里,但是在实际的使用过程中发现测试人员明明已经执行过的测试用例,有些class覆盖率统计却为0、有些能正常统计出来,到底是怎么回事呢?接下来分享下解决这个问题的排查过程。
前提:代码没有任何变更,相同的代码、jdk8版本一样、mvn版本一样
第一步:jacoco本身是否支持类修改后,已经执行过的测试用例是否已经支持合并到最新统计中?
jacoco的源码本身是不支持同类修改后的再次合并统计的,因为数组探针不一样导致,因为我们是在jacoco多版本exec合并_jacoco合并exec-CSDN博客的基础上做的,也就解决了多版本合并不上的问题,因此不存在统计不上的问题,继续找原因
第二步:把被代理的应用代码本地部署、本地收集覆盖率
可以正常统计到,说明jacoco工具本身没问题,那么有点纳闷了,为什么部署在服务器统计不到?继续找原因
第三步:公司的CICD流程环节是否有问题?
从公司的CICD上入手考虑,先解释几个名词、简单交代下背景哈
a:devops-公司自主研发的交付流平台
b:工单-指一个需求对应的所需开发应用的代码工单号
c:部署平台-专门用于部署应用的自动化平台
d:开发模式:90%业务线基于分支上线,10%基于主干上线(gitlab的CICD),为什么是这样?原因很复杂,这样就不展开说了,现状如此。
CICD主流程:
1、在devops平台上创建需求关联开发工单、下拉分支
2、开发完成后,在devops上编译打包,实际调用的jenkins实现的代码编译打包,打出的jar/war包ftp到文件服务器
3、提测到测试阶段开始测试,测试人员根据包所在地址在部署平台上手动选择服务器部署;
4、测试人员测试完成后,开发根据测试过的版本去上线
5、上线验证没问题后,合并分支代码到主干
从整个CICD流程上来看,我们是把触发代码覆盖率应用初始化的步骤放在了部署这一步,当测试人员在部署平台部署的时候触发覆盖率服务,过程中需要下载代码、然后编译;而这时候编译出的class和从jenkins上编译出的包部署在服务器上的应用做代理通信,最后通过定时任务xxl-job收集覆盖率。即使代码没有任何变更,有些类的覆盖率统计也统计不到,问题大概就出在这里,顺着这个思路继续往下找原因。
第四步:会不会是两次编译的class不一样?
把从jenkins编译出的class(即应用打包的class)复制到覆盖率收集服务下,然后做代理通信,发现测试用例被统计到了,问题终于快找到了,应该是两次编译生成的class不一样。于是我把两次编译的class都搞到本地,做对比,我发现有些class完全一样,有些class却有差异,而有差异的都有个共同特点:使用了lambda表达式,如下图:
查资料解决lambda表达式?
Lambda 表达式在 Java 中被转换为一种叫做 "匿名内部类" 的特殊类型,这个过程发生在编译阶段。编译器会为每个 Lambda 表达式生成一个唯一的、匿名的类文件,这个类文件通常以 $
符号和一些数字结尾来确保其唯一性。这样做的原因有几个方面:
-
匿名性:由于这些类没有显式的类名,所以被称为匿名类。Lambda 表达式的本质就是简洁地表示匿名函数,因此由它们生成的类也是匿名的。
-
实例化要求:Lambda 表达式可能捕获上下文中的局部变量和参数,这要求必须为每个不同的 Lambda 表达式实例化一个新的类,因为每个类都可能有不同的捕获需求。
-
唯一性:为了防止命名冲突,并确保在类加载器中不会出现重复的类名,编译器生成的类名是自动生成的,并且是唯一的。
-
实现细节:Java 语言规范并不规定具体的类名生成策略,这是 JVM 的具体实现细节。不同的 JVM 供应商或不同版本的同一供应商可能会采用不同的策略来生成类名。
-
避免冲突:如果每次编译都生成相同的类名,那么当多个类加载器加载了相同代码的不同版本时,可能会导致类名冲突,进而导致类加载错误或不可预期的行为。
-
字节码层面:Lambda 表达式编译后的类包含实现了对应接口方法的字节码,以及与 Lambda 表达式相关的其他信息,如捕获的变量等。
综上所述,Lambda 表达式编译时每次都不一样,它会动态生成calss,是因为需要确保每个 Lambda 表达式的唯一性、匿名性和上下文的正确捕获,同时防止潜在的类名冲突
第五步:结论-保证编译部署的class、应用包一致性
至此问题圆满解决!!!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)