前端代码覆盖率增量计算
关于后台的代码增量的逻辑已经有比较成熟的方案了。 根据javaparser解析前后的文件的方法列表,判断是否有新增或者修改的方法。
前端代码覆盖率增量覆盖的困难
针对前端代码覆盖率并不能像java那块那么简单,有专门的javascript的解析器,能够获取到这个js文件中所有的方法。所以套用原有的java那套逻辑基本是不太可行的。所以我们需要另辟蹊径来解决这个问题。
java的增量代码diff 我们是从解析源码的文件入手的,那针对js既然这套不行,有没有方式能够从覆盖率结果数据入手,去解决这个事情呢?
如果了解前端代码覆盖率的同学可能都清楚,前端的覆盖率收集是根据浏览器提交的coverage数据来的。而coverage的数据其实是大有来头的。
我们看一个数据
/**** * `path` - the file path for which coverage is being tracked* * `statementMap` - map of statement locations keyed by statement index* * `fnMap` - map of function metadata keyed by function index* * `branchMap` - map of branch metadata keyed by branch index* * `s` - hit counts for statements* * `f` - hit count for functions* * `b` - hit count for branches*/
{path: filePath,statementMap: {"5": {"end": {"line": 10,"column": 30},"start": {"line": 10,"column": 26}},},fnMap: {},branchMap: {},s: {"5": 10290,},f: {},b: {}
}
以上的内容中statementMap
中的5
代表标记的对应的代码块为第10行,列则是从26到30, 同时映射到s
中 这个代码块被执行了10290次。
这块的数据其实也完整的说明了对应的文件中,代码/分支/方法是否覆盖的情况。
思路
那么是不是可以这么去考虑呢?从git diff中对比得到对应文件的改动行数,然后再对应到这块的数据上,如果修改的代码行 是在statemanMap
/ fnMap
/ branchMap
的覆盖范围的话就保留这块的数据,如果说改动行中,不存在有这块的内容则从对象中将这块的内容剔除掉。这样子就可以得到增量的数据了。
但是我们是不是直接针对用户提交的coverage数据做处理呢?
答案是不行的。 我们需要了解一个问题,之前我们在 聊聊前端代码覆盖率 (长文慎入) 中提到过用户提交的coverage数据并不是完整的反应到原本的代码行上,主要是针对typescript这块,因为如果你的编译是经过ts-loader -> babel-loader 处理的话。得到的coverage中的数据中的line的值,其实跟源码中的line会出现不一致的情况。而istanbul这块是会根据sourceMap 重新映射回去的。
那哪里的数据才是正在正确的呢? 答案其实在通过nyc api生成的报告目录下, 当你的api指定了reporter包含有 json的情况下,就会在覆盖率报告的目录下生成有 coverage-final.json
。 这里的数据其实跟coverage数据基本是一致的,并且这里的数据已经经过istanbul校正过。所以我们可以信任这块的数据。
解决
从git api中获取到改动行,判断statemanMap
/ fnMap
/ branchMap
的开始行及结束行的范围是否包含了改动行。如果在对应的范围那么则保留对象数据,如果不在,则移除掉对应的对象。如此剩下的就是改动范围的覆盖情况
所以我们可以这么处理
/*** 根据代码codeDiff,过滤掉未改动的语句* @param fileFinal 对应文件的覆盖率数据情况,格式就是我们上述提到的数据* @param statements * @return*/
private void handleStatements(List<Integer> codeDiff, Coverage fileFinal, CoverageSummary statements, CoverageSummary lines) {List<String> keys = new ArrayList<>();Map<Integer, Integer> line = new HashMap<>();// 这里的key 是0, 1, 2, 3 "statementMap":{"0":{"start":{"line":9,"column":22},"end":{"line":39,"column":1}} ;; "s":{"0":10150,"1":10150,"2":0,"3":0},for (String key : fileFinal.getStatementMap().keySet()) {if (!isDiff(codeDiff, fileFinal.getStatementMap().get(key).getStart().getLine(), fileFinal.getStatementMap().get(key).getEnd().getLine())) {keys.add(key);}}// 将不包含改动行的桩删除for (String key : keys) {fileFinal.getStatementMap().remove(key);fileFinal.getS().remove(key);}computeCoverageSummary(getLineCoverage(fileFinal), lines);computeCoverageSummary(fileFinal.getS(), statements);
}
这里关于statement/line/fun的统计计算这里就不详细描述了,主要可以参考 file-coverage 中的各个值的计算逻辑。
所以我们举一个简单的例子来说明下:假设 client/src/utils/location.js
的coverage数据如下:
{"/app/thirdCode/c94933a0-7250-11eb-8c93-c9620716ef34_1/xxx/client/src/utils/location.js": {"path": "/app/thirdCode/c94933a0-7250-11eb-8c93-c9620716ef34_1/xxx/client/src/utils/location.js","statementMap": {"0": {"start": {"line": 9,"column": 39},"end": {"line": 9,"column": 54}},"1": {"start": {"line": 10,"column": 25},"end": {"line": 10,"column": 52}},"2": {"start": {"line": 11,"column": 26},"end": {"line": 11,"column": 48}},"3": {"start": {"line": 13,"column": 4},"end": {"line": 19,"column": 5}},"4": {"start": {"line": 14,"column": 8},"end": {"line": 17,"column": 9}},"5": {"start": {"line": 15,"column": 12},"end": {"line": 15,"column": 37}},"6": {"start": {"line": 16,"column": 12},"end": {"line": 16,"column": 21}},"7": {"start": {"line": 18,"column": 8},"end": {"line": 18,"column": 37}},"8": {"start": {"line": 20,"column": 22},"end": {"line": 20,"column": 45}},"9": {"start": {"line": 21,"column": 20},"end": {"line": 21,"column": 72}},"10": {"start": {"line": 23,"column": 4},"end": {"line": 25,"column": 5}},"11": {"start": {"line": 24,"column": 8},"end": {"line": 24,"column": 50}},"12": {"start": {"line": 27,"column": 4},"end": {"line": 27,"column": 19}},"13": {"start": {"line": 36,"column": 25},"end": {"line": 36,"column": 78}},"14": {"start": {"line": 37,"column": 19},"end": {"line": 40,"column": 10}},"15": {"start": {"line": 38,"column": 8},"end": {"line": 38,"column": 31}},"16": {"start": {"line": 39,"column": 8},"end": {"line": 39,"column": 19}},"17": {"start": {"line": 42,"column": 4},"end": {"line": 44,"column": 5}},"18": {"start": {"line": 43,"column": 8},"end": {"line": 43,"column": 29}},"19": {"start": {"line": 46,"column": 4},"end": {"line": 48,"column": 5}},"20": {"start": {"line": 47,"column": 8},"end": {"line": 47,"column": 35}},"21": {"start": {"line": 50,"column": 4},"end": {"line": 50,"column": 18}}},"s": {"0": 43,"1": 43,"2": 43,"3": 43,"4": 43,"5": 0,"6": 0,"7": 43,"8": 43,"9": 43,"10": 43,"11": 43,"12": 43,"13": 2184,"14": 2184,"15": 6552,"16": 6552,"17": 2184,"18": 2184,"19": 0,"20": 0,"21": 0},"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9","hash": "26596d813cde8cfd5d6449001d4e49f4283c164a"}
}
以上的数据我们省掉了 fnMap以及branchMap的数据。
而我们的的codeDiff的数据:
说明改动的行数只是49-50行
所以处理过的coverage的结果数据为
{"s": {"21": 0},"hash": "26596d813cde8cfd5d6449001d4e49f4283c164a","path": "/app/thirdCode/c94933a0-7250-11eb-8c93-c9620716ef34_1/xxx/client/src/utils/location.js","statementMap": {"21": {"end": {"line": 50,"column": 18},"start": {"line": 50,"column": 4}}},"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9"
}
相应的fn, branch也是相应的处理。
不足:
上述的方式其实存在一个问题,前端的增量覆盖计算的逻辑并不是跟java的增量的逻辑一致的,java的最小增量的计算单位是方法,而前端的最小增量单位是语句。所以并不能很好的得到结果是前端某个代码改动后,需要覆盖这个代码所在的方法的内容,而只是需要覆盖到改动的语句就可以了。
前端代码覆盖率增量计算相关推荐
- 前端代码覆盖率遇到问题及总结(一)
在讲之前得说下 前端覆盖率的水真的是很深的,其实到目前为止还有很多未解之谜,由于对babel的编译以及ast了解的不是很多.所以确实分析问题起来很困难. 前端代码覆盖率方案 关于前端代码覆盖率还不了解 ...
- 非常复杂,上双11数据大屏背后的秘密:大规模流式增量计算及应用
回顾大数据技术领域大事件,最早可追溯到06年Hadoop的正式启动,而环顾四下,围绕着数据库及数据处理引擎,业内充斥着各种各样的大数据技术.这是个技术人的好时代,仅数据库领域热门DB就有300+,围绕 ...
- 一个前端js分页计算
<div id=rrapp><table id="rightHolder" class="layui-table" lay-skin=&quo ...
- 音视频中时间戳增量计算
https://blog.csdn.net/u012635648/article/details/78695619 https://blog.csdn.net/peckjerry/article/de ...
- 2021前端面试经典计算题总结。
1. 给出一个string, 倒序输出该句子,其中的每个单词本身并不会翻转, 比如 "I love China" ->"China love I" var ...
- 前端遇上Go: 静态资源增量更新的新实践
为什么要做增量更新 美团金融的业务在过去的一段时间里发展非常快速.在业务增长的同时,我们也注意到,很多用户的支付环境,其实是在弱网环境中的. 大家知道,前端能够服务用户的前提是 JavaScript ...
- iOS代码覆盖率(二)-增量覆盖率自动化实践
全量代码覆盖率可以直观的看到整个App的代码的覆盖率情况,但是往往有用的或者被关注的是增量代码覆盖率数据.经过不断的学习和探索,发现在基于git diff能力,通过一系列的处理获取我们想要的增量的信息 ...
- 头条项目推荐的相关技术(四):离线文章画像的增量更新及离线文章相似度计算
1. 写在前面 这里是有关于一个头条推荐项目的学习笔记,主要是整理工业上的推荐系统用到的一些常用技术, 这是第四篇, 上一篇文章整理了离线文章画像的计算过程,主要包括TFIDF和TextRank两种技 ...
- 大数据计算框架与平台--深入浅出分析
http://mp.weixin.qq.com/s/s2DnbgieeQockaLKdZDCzA?utm_source=tuicool&utm_medium=referral 1. 前言 计算 ...
最新文章
- 用AI还原李焕英老照片动态影像
- gitk、Git GUI 图形化工具中文显示乱码的解决方案
- 正则表达式懒惰贪婪和replace函数
- PostgreSQL 电商业务(任意维度商品圈选应用) - json包range数组的命中优化 - 展开+索引优化...
- Mac OS X 在Finder新建文本文件
- ubuntu使用KVM创建虚拟机
- H5页面在iOS网页数字颜色自动被改变成蓝色
- 桌面虚拟化之用户行为审计
- VMware vCenter Server6.5升级至6.7
- Deepin Linux已经做得相当不错了
- delphi xe3 oracle,delphixe3
- 卸载office 2003出现pro11.msi
- 目标检测算法综述(近20年)
- imx6ull-qemu 裸机教程1:GPIO,IOMUX,I2C
- 大数据毕设 - 网络游戏数据分析与可视化(python 大数据)
- STC12驱动PCF8575
- UG NX 12 矢量构造器
- XCode下Object C和C++混合编译
- 从DPU看未来网络架构的演进趋势
- 【AI】《ResNet》论文解读、代码实现与调试找错