写了一个简单的 spring demo,2 个 Java 文件
1,用 postman 发请求,覆盖了 Java1,执行 ant dump , ant report 看到 Java1 覆盖率 100%
2,修改 Java2 代码,提交,部署服务
3,执行 ant dump , ant report 发现 Java1 和 Java2 的覆盖率都是 0
这种明显不满足日常测试需求,即使是统计差异覆盖率 (测试分支和 master 分支),测试分支代码改动 覆盖率也变成了 0,有什么好的办法?
+1
exec 文件合并了解一下~~
jacoco 在 agent 模式下的覆盖率是在应用内存中以 map 形式进行存储,修改代码后重新部署肯定会清空,还有即使 ant dump 保存到本地,如果 class 文件出现变更也不会合并成功。
也就是你第一次部署,执行 ant dump,本地 exec 文件保存 java1、java2 的覆盖率,修改 java2,部署后,再次执行 ant dump,ant merge 合并,ant report 查看报告,java1 可以展示 2 次部署的总覆盖率,java2 由于文件出现变更,只显示最新的覆盖率。
ant merge 是 exec 文件合并吗?我合并 exec 文件后 ant dump,2 个文件的覆盖率都是 0
你的 class 文件是怎么来的?report 覆盖率是 0 不一定真的是覆盖率为 0,也可能是打包的方式或者版本问题,导致 classid 对不上。你可以先对 exec 文件做 execinfo 操作,看下是否有覆盖数据,merge 后再看下 merge 后的 exec 文件有没有覆盖数据。先确定是 exec 文件的问题还是 report 的时候出的问题。
建议可以先用 jacococli.jar 进行操作 (java -jar jacococli.jar --help)。操作的时候可以看下日志。
我试试这种方式。。
我是用 Jenkins 拉代码,执行 ant 命令的,因为代码改动了 jar 包变了,所以覆盖率为 0
第一次执行后覆盖率如下,ant report 生成报告:
359ada1e6c61023e 3 of 3 com/example/spring/http/SwaggerRestful
695ddd1b39e5b86d 13 of 32 com/example/spring/http/HttpServer
修改代码后部署服务,执行操作后查看覆盖率,,ant report 生成报告:
2f7ac4ed6385f513 9 of 32 com/example/spring/http/HttpServer
359ada1e6c61023e 1 of 3 com/example/spring/http/SwaggerRestful
exec 文件合并后覆盖率:
2f7ac4ed6385f513 9 of 32 com/example/spring/http/HttpServer
359ada1e6c61023e 3 of 3 com/example/spring/http/SwaggerRestful
695ddd1b39e5b86d 13 of 32 com/example/spring/http/HttpServer
report 的时候用合并后的 exec 文件,classes 如果是第一次的 则报告和第一次的一样,classes 是第二次的则报告和第二次的一样
有什么办法可以把 2 次的报告合并导一起?
有点麻烦 除非你自己去改 jacoco 的源码,因为 jacoco 的源码逻辑是根据 classId 进行合并的,不是按照 className 进行合并的,所以你虽然两个类包名类名都一样,但是 classId 是不一样的。我们自己是做了二次修改,根据 className 做了一次合并处理
public void put(final ExecutionData data) throws IllegalStateException {
final Long id = Long.valueOf(data.getId());
final ExecutionData entry = entries.get(id);
if (entry == null) {
entries.put(id, data);
names.add(data.getName());
} else {
entry.merge(data);
}
}
是的,你可以看下这块的逻辑,这个就是按照 classId 然后做数据的合并的。所以如果一定要 只能修改这块的逻辑
看你的需求是想要做什么了,我们是做了一层二次处理,如果 id 找不到探针数据,就用 className 再次找一遍做个保底的情况,所以我们在 ExecutionDataStore
中 又增加了一个 private final Map<String, ExecutionData> classEntries = new HashMap<String, ExecutionData>();
这个变量去维护 className 跟探针的关系
Map<String, ExecutionData>
只用这一个 map 就够了吧,把 className 作为 key
针对 class 中新增方法这种情况,建议这个类就不要做合并的动作了,因为 jacoco 的源码中不单单是针对不同的 classId 不能合并,就算你改成了 className, 但是他还会去判断探针数组长度,两个探针数组长度不一样也不会合并成功,就算你强行要合并 合并的逻辑又是什么呢?
这个其实修改很容易的,因为我那边是改了很多其他部分的东西,不能发你。 你可以看下这篇文章。里面写到了关于如何修改的逻辑