Apache DolphinScheduler 项目笔记 — 1. 问题定位和排查问题
导语:
Yuanhao Ji 同学是《暑期 2021 - API 模块 UT 测试问题解决》项目负责人,本文记录了他是如何排查和定位问题。
1. 背景
问题:在部分 UT 中使用 PowerMock 后,导致 Sonar 不能获取对应的测试报告。
大概原因:PowerMock 模拟 JDK 的静态方法、构造方法、final 方法、私有方法时,需要把使用这些方法的类加入到 @PrepareForTest 注解中,从而导致单元测试覆盖率不被统计。
2. 思路
2.1 明确问题出处,缩小定位范围

DolphinScheduler UT 中使用了 PowerMock 作为单元测试模拟框架,由 JaCoCo 统计各项覆盖率指标,最后由 Sonar 存储和管理覆盖率数据。而问题表现为 —— Sonar 中的某些 UT 覆盖率为 0,但是 Sonar 只是一个代码质量管理平台,覆盖率数值并不是由它得出的,Sonar 只是读取了 JaCoCo 生成的测试报告。那么,很容易看出,这个问题一定与 JaCoCo 脱不了干系。
进一步观察发现,并非所有 UT 的覆盖率都有问题,只用到 JUnit 的 UT 就可以正常获取覆盖率,而所有出现覆盖率问题的 UT 都少不了 PowerMock 的影子。
因此,覆盖率问题一定与 PowerMock 和 JaCoCo 有关。
2.2 搜集资料,寻找相似问题
分析问题之后,我们首先可以借助搜索引擎找到与之相似或相同的问题,通过了解这些问题的背景和解决方案也许可以找到我们问题的关键点。
基于以上分析,以 JaCoCo、PowerMock、覆盖率 这三个关键字在 Google、Baidu 等搜索引擎上搜索资料。幸运的是,网上有大量同类问题,并且都与 JaCoCo、PowerMock 有关。
其中,正如 Code-coverage-with-JaCoCo[1] 中所说 —— There is NO WAY TO USE PowerMock with JaCoCo On-the-fly instrumentation。PowerMock 和 JaCoCo 的 On-the-fly instrumentation 之间存在问题。经验证发现,DolphinScheduler 目前正是使用的这两者结合的方式,因此这应该就是问题的关键所在。
2.3 分析问题出现原因
基于搜索结果和官方文档,分析问题出现原因。
首先,如 JaCoCo Class Ids[2] 中的描述,JaCoCo 基于 CRC64 算法计算得到 64 位的 Class Id,用它来标识 Java 类,在运行时为每个加载的类采样执行数据并存储到 *.exec 文件中,在分析时(例如生成报告),Class Id 用于将分析的类与执行数据相关联。
而出现覆盖率为 0% ,就是因为待测试的类与 JaCoCo 实际采样的类不一致,也即通过 CRC64 算法计算的 Class Id 改变,从而导致待测试类的测试报告中覆盖率始终为 0。
那么,为何会出现这种 Class Id 改变的情况呢?上述页面中也给出了答复 —— 这种情况通常发生在配置 JaCoCo 代理之前配置了另一个 Java Agent,或者特殊的类加载器预处理了这些类文件,例如:Mocking frameworks、Application servers、Persistence frameworks。而 PowerMock 就是一种 Mock 框架,进一步了解其原理得知,JaCoCo 在加载 class 时会事先把统计代码插入到 class 中(即插桩),当执行到某个测试类时,PowerMock 检测到该类使用了@PrepareForTest 注解,就会在加载该类时使用 Javassist 直接从 class 文件中重新读取字节码,导致 JaCoCo 的修改丢失,稍后 JaCoCo 统计的 class 是被修改之后的,而被修改之后的 class 中并没有 JaCoCo 所插入的统计代码,并且 class 文件发生变化后 Class Id 也与加载时不一致。在分析时,测试结果无法关联到待测试类,最终导致覆盖率始终为 0。
如下图所示,Demo 类后面还跟有 MockitoMock 的字样,说明这是一个由 PowerMock 模拟的对象,而 JaCoCo 却错把它以为是最开始时所加载的 Demo 类。

2.4 制定解决方案
JaCoCo 的 offline instrumentation 可以解决此类问题,它的原理是这样的:在测试前先对 class 文件进行插桩,然后生成插过桩的 class 文件或 jar 包,测试插过桩的 class 和 jar 包后,生成动态覆盖信息到文件,最后统一对覆盖信息进行处理,并生成报告。
On-the-fly 模式进行代码覆盖分析更方便和简单,无需提前进行字节码插桩,无需考虑 classpath 的设置。
但存在如下情况则不适合 On-the-fly,需要采用 offline 提前对字节码插桩:
(1)运行环境不支持 java agent。
(2)部署环境不允许设置 JVM 参数。
(3)字节码需要被转换成其他的虚拟机如 Android Dalvik VM。
(4)动态修改字节码过程中和其他 agent 冲突。
(5)无法自定义用户加载类。
而目前问题就是因为动态修改字节码过程中与 PowerMock 冲突,因此必须使用 offline 模式。
[1] https://github.com/powermock/powermock/wiki/Code-coverage-with-JaCoCo
[2] https://www.eclemma.org/jacoco/trunk/doc/classids.html
Apache DolphinScheduler 项目笔记 — 1. 问题定位和排查问题的更多相关文章
- 感谢有你!Apache DolphinScheduler 项目 GitHub star 突破 8k
本周伊始,Apache DolphinScheduler 项目在 GitHub 上的 Github Star 总数首次突破 8K.目前,Apache DolphinScheduler 社区已经拥有 C ...
- Apache DolphinScheduler(海豚调度) - 1.3 系列核心表结构剖析
Apache DolphinScheduler 是一个分布式去中心化,易扩展的可视化 DAG 工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用. 近日 ...
- 金灿灿的季节 - Apache DolphinScheduler收获5位新Committer
在这个金灿灿的收获季节,经过 Apache DolphinScheduler PPMC 们的推荐和投票,Apache DolphinScheduler 收获了 5 位新Committer .他们是:n ...
- 金秋十月 - Apache DolphinScheduler 收获 2 位新 Committer
点击上方蓝字关注 Apache DolphinScheduler Apache DolphinScheduler(incubating),简称"DS", 中文名 "海豚调 ...
- 新一代大数据任务调度 - Apache DolphinScheduler喜提十大开源新锐项目 & 最具人气项目
经 10000+ 开发者公开票选,20+专家评审. 10+ 主编团打分,历经数月打磨,11 月 19 日,由InfoQ 发起并组织的[2020中国技术力量年度榜单评选]结果正式揭晓. 2020 年度十 ...
- 【喜讯】Apache DolphinScheduler 荣获 “2020 年度十大开源新锐项目”
经 10000+ 开发者公开票选,20+专家评审. 10+ 主编团打分,历经数月打磨,11 月 19 日,由InfoQ 发起并组织的[2020中国技术力量年度榜单评选]结果正式揭晓. 2020 年度十 ...
- 大数据平台迁移实践 | Apache DolphinScheduler 在当贝大数据环境中的应用
大家下午好,我是来自当贝网络科技大数据平台的基础开发工程师 王昱翔,感谢社区的邀请来参与这次分享,关于 Apache DolphinScheduler 在当贝网络科技大数据环境中的应用. 本次演讲主要 ...
- Apache DolphinScheduler 2.X保姆级源码解析,中国移动工程师揭秘服务调度启动全流程
2022年1月,科学技术部高新技术司副司长梅建平在"第六届中国新金融高峰论坛"上表示,当前数据量已经大大超过了处理能力的上限,若信息技术仍然是渐进式发展,则数据处理能力的提升将远远 ...
- Apache DolphinScheduler 3.0.0 正式版发布!
点亮 ️ Star · 照亮开源之路 GitHub:https://github.com/apache/dolphinscheduler 版本发布 2022/8/10 2022 年 8 ...
随机推荐
- einsum函数介绍-张量常用操作
einsum函数说明 pytorch文档说明:\(torch.einsum(equation, **operands)\) 使用基于爱因斯坦求和约定的符号,将输入operands的元素沿指定的维数求和 ...
- [算法学习] 换根dp
换根dp 一般来说,我们做题的树都是默认 \(1\) 为根的.但是有些题目需要计算以每个节点为根时的内容. 朴素的暴力:以每个点 \(u\) 作为 \(root\) 暴力dfs下去,复杂度\(O(n^ ...
- 渗透测试之sql注入点查询
一切教程在于安全防范,不在于攻击别人黑别人系统为目的 寻找sql注入点方法: 拿到网页后进行查找注入点: 1.通过单引号 ' ; 在 url 后面输入单引号进行回车(如果报错可能存在sql注入为 ...
- 微前端(qiankun)主应用共享React组件
前言 最近需要重构一个老项目,定的方案用微前端去改造.主应用是老的项目,微应用是新的项目,由于重构时间比较紧张,子应用还需要使用父应用的一些组件.过程中遇到一些问题,记录一下. 方案 我们知道qian ...
- DAST 黑盒漏洞扫描器 第四篇:扫描性能
0X01 前言 大多数安全产品的大致框架 提高性能的目的是消费跟得上生产,不至于堆积,留有余力应对突增的流量,可以从以下几个方面考虑 流量:减少无效流量 规则:减少规则冗余请求 生产者:减少无效扫描任 ...
- Vue回炉重造之如何使用props、emit实现自定义双向绑定
下面我将使用Vue自带的属性实现简单的双向绑定. 下面的例子就是利用了父组件传给子组件(在子组件定义props属性,在父组件的子组件上绑定属性),子组件传给父组件(在子组件使用$emit()属性定义一 ...
- Mybatis+SpringBoot 项目All elements are null
xml文件内容如下 查出来的集合长度是有的,但是会出现All elements are null 解决方案: 注意我的xml文件全部是这样的,并且我调用的sql返回值是 resultType=&qu ...
- Codeforces Round #779 (Div. 2)
A 题目连接 题目大意 给一个01串,其中每一个长度大于等于2的子区间中0的数量不大于1的数量,最少插入多少1 思路 寻找 00 和 010 00 -->0110 加2 010 --&g ...
- Tapdata 的 2.0 版 ,开源的 Live Data Platform 现已发布
https://www.bilibili.com/video/BV1tT411g7PA/?aid=470724972&cid=766317673&page=1 点击上方链接,一分钟快速 ...
- P1494 小Z的袜子 莫队
题干 就是将$add$和$del$函数里的$ans$变化变成组合数嘛, 先预处理出$x$只相同袜子一共有$f[x] = 1+2+...+$$(x-1)$种组合, 要注意,由于$f[x]$是一直加到$x ...