前端质量提升利器 - 马可代码覆盖率平台

本文根据 Song Jiachao 老师在“2021 vivo 开发者大会"现场演讲内容整理而成。公众号回复【2021VDC】获取互联网技术分会场议题相关资料。

一、背景
1.1 项目特点
随着互联网科技的飞速发展,越来越多的公司将敏捷开发的流程引入到项目迭代中,所以越来越多的项目呈现出三个特点:

1)迭代周期短:各种倒排,压排期,一周一小版本,两周一大版本,甚至有的项目每天都在发版,苦不堪言。
2)需求变更频繁:我们的产品经理不是在推翻自己,就是在推翻自己的路上,所以我们经常也会开玩笑跟产品经理说:来来来,你立个字据,保证一下以后再也不改需求了。产品经理这时候信誓旦旦的说:好好好,你把这个需求改了,我保证给你立字据,下次再也不改了。可是并没有什么作用,需求依然改的很频繁。当然了,这也不能怪产品经理,面对着瞬息万变的市场环境,我们有时候需要用这种试错的方式来快速的找到正确的方案。
3)系统复杂度高:前端已经不仅仅是画画页面那么简单了,大家可以从现在的前端招聘信息中就可以看出来。分布式、微服务、中间层、各种琳琅满目的架构,让本就复杂的业务,变得更加复杂。
随着项目的这些特点越来越明显,对我们开发和测试的挑战也变得越来越大。
1.2 烦恼
所以我们会有如下的一些烦恼:

有这样的烦恼,归根结底有两方面的原因:
测试人员:他们不知道开发代码的改动点在哪里,影响点在哪里,很难用精准化的测试方案,来提升测试效率,所以为了保险起见,只能把相关功能全部测一遍
开发人员:他们无法全面的知道每一行代码的执行情况,很难通过执行数据,来分析哪些代码是有用的,哪些代码是没用的,哪些代码测试已经验证过,哪些代码还没有被验证

所以我们迫切的需要一个平台,能够方便的看出代码的改动点和执行情况,而这个平台就是集成代码覆盖率平台。
1.3 方案
所谓的集成代码覆盖率平台,是指在集成测试期间,采集代码覆盖率,并上报到系统中进行合并展示的平台。

1.4 难点
既然有解决方案,为什么现在市面上很少有这样的产品推出呢?我们在研究这方面的时候,发现了两个非常大的技术难点。
第一个难点是:数据合并难。我们都知道,前端所有的测试都是在各端进行的,测试产生的数据留在各个终端,很难将这些留在各个终端的数据进行收集和合并。
第二个难点是:数据失效快。前端代码发版非常频繁,在测试的时候,每天可能发版好多次,发版代表虽然是同一份文件,但里面的内容可能完全不一样了,这样就会导致之前采集的覆盖率完全失效了。

通过不断的尝试,我们终于解决了这两个问题,于是就诞生了马可代码覆盖率平台。
二、马可平台的优势及亮点
2.1 优势及亮点
马可平台是一个完备的代码覆盖率平台,具有以下几个亮点:
支持一键接入:不挑业务,框架,对现有代码零侵入,一键即可接入;
支持增量报告:能够让使用者更加精准的了解代码覆盖率情况;
支持多种语言:马可平台不局限于前端,也能服务后端;
支持多种工具:方便用户使用,比如代码对比,gitblame 等;
支持多个用户:多种报告的实时合并与查看;
支持大盘监控:通过大盘实时查看覆盖率走势,了解项目质量趋势;
支持消息通知:定时推送项目覆盖率情况;
支持独立部署:不仅支持第三方直接接入,还支持一键私有化部署。

2.2 体验
2.2.1 详情页
下图上的第一点:当前版本改动了哪些文件,我们会将所有的改动文件通过树状结构图展示在第一个区域,让用户一眼就能清楚当前版本到底改了多少个文件
下图上的第二点:当前文件改动哪些地方,我们通过代码对比的方式,直观的将每一个文件的改动点显示在第二个区域,让用户一眼就能看到这个文件到底改了哪几行代码
下图上的第三点:当前改动是否被测试验证过,刚刚第二点我们标记出了一份文件的到底哪几行发生了变更,那么第三点就是将变更的代码标记出来是否被验证过。
有了这三点标记,我们就将改动点和测试过程进行了完美的结合,让测试结果一目了然。

2.2.2 趋势图
通过项目趋势图,我们可以清楚的看出项目覆盖率走势,了解项目质量趋势。

2.2.3 概览
目前马可平台已经稳定运行近 3 个月了,服务了 39 个项目,生成了 133 分报告。

2.3 价值
通过马可平台我们就将测试关注的四个点即:修改点、影响点、测试点和测试结果,给紧密的联系起来,同时将之前的缺乏数据的评估转化成精确的,有客观依据可量化的评估。

三、马可平台的技术方案
马可平台的技术方案共有 4 个小部分:首先会介绍马可平台的整体架构,然后分别从接入层、服务层和展示层,三个方面加以详细的说明。
3.1 整体架构图
马可平台分为三个层:接入层、服务层和展示层;
接入层:我们的目标是一键接入,多语言适配,区分环境和智能上报。目前针对 Web 端的适配已经全部完成了,正在适配其他技术栈,比如小程序、Node.js、Typescript。同时我们还规划了其他语言的接入方式,让马可平台变成全语言的代码覆盖率平台。
服务层:主要是对报告的各种处理,比如报告管理、用户管理、项目管理等功能。
展示层:主要是对服务层的一个延伸,通过可视化的方式,提供更加便捷的报告查看和管理等功能。

3.2 数据流向图
通过数据流向图,我们将一份报告从接入层到服务层再到展示层给串联起来形成一个完美的闭环。

3.3 接入层
接入层主要就是接入和上报这两点;
针对接入:我们提供各语言插桩方案、插桩规范、以及接入指导。
针对上报:主要有各语言的采集方案,上报数据标准和上报方案。

3.3.1 接入
插桩维度:
通常我们会将插桩分为 4 个维度:语句覆盖率,函数覆盖率,分支覆盖率,和行覆盖率。

插桩过程

马可插桩
这是马可平台,js 插桩的部分代码,主要做了三件事;
第一步:获取文件相对路径
为啥是相对路径?因为马可代码覆盖率是一个平台,所以我们需要获取相对路径,让文件路径和项目进行关联,而不是与打包机器关联。
第二步:调用了 istanbul-lib-instrument 进行插桩我们没有完全重写插桩代码,而是借助了开源的力量,让马可平台更加轻量化、通用化。
第三步:添加自定义参数这些参数都非常重要,指明了当前报告的重要信息。
这样我们就简单完成了 js 语言的插桩适配,其他语言可以同样参考这样的思路。

3.3.2 上报
上报就是采集和发送的过程。
针对采集:主要获取两个信息,覆盖率信息和项目信息,两者缺一不可。
针对发送:各个端会有很大的差异,我们提供了一定的建议。比如在 web 中可以监听 Visibilitychange 事件,而在小程序中可以监听 onShow 和 onHide 事件,如果是在 Node 等其他服务端中可以通过定时任务进行上报。

3.4 服务层
马可的服务层提供了很多的功能,这里我们挑报告管理和用户管理,这两个比较典型的功能进行介绍。

3.4.1 报告管理
报告三要素:首先一份完整的报告需要有三个基本要素:覆盖率信息,项目信息,和文件信息。
覆盖率信息包括:语句、分支、函数、行四个覆盖率。
项目信息包括:项目配置,分支信息,文件 hash,构建时间。
文件信息包括:文件地址、文件内容和 Git 信息。
通过接入层采集的覆盖率信息和项目信息,然后关联 Git 平台的文件信息,通过这种方式才能让马可变成一个多用户、多报告支持的覆盖率平台。

3.4.2 合并流程
上一个步骤我们采集到了覆盖率,下面我们聊一聊马可平台是如何进行报告合并的,我们先来考虑两种情况:
第一种情况:文件没有变更;
就是我们下图左边的部分,文件没有变更的时候,有两个测试,小美和小花分别产生了两个报告信息,这种情况改如何进行合并呢?
第二种情况是:文件发生了变更;
同一份文件,文件的内容发生了变更,变更文件的行号前后无法一一对应,比如变更前文件的第 10 行,到了变更后的文件,就变成了第 6 行,这两行其实是一样的,但因为其他行的删减导致了,这一行的行号也发生了变化,这种情况又该如何合并呢?

带着上面两个问题,我们来整理一下报告的和合并流程。
比较复杂的就是对报告构建时间进行对比,构建时间比较会有三个结果,分别对应不同的合并流程。

3.4.3 变更内容获取
在主流的 git 托管平台,都提供了 API 接口的方式,返回 Git 的信息,比如可以通过 Gitlab 的 compare 接口就可以将两个分支的对比信息给拿到,通过解析返回的信息,我们就可以知道文件的变更内容。

3.4.4 用户管理
为了能够让马可平台尽可能的简单化,我们登录使用了通用 Oauth 登录方式,通过这种方式,不仅解决了登录问题,同时也解决了代码权限的问题,真是一举多得,当然我们在设计登录的时候,充分考虑了主流的 Git 平台,比如 Gitlab、Github、Gitee 等,也就是说托管在这些平台中的代码,都可以一键接入马可代码覆盖率平台。

3.5 展示层
这就是马可平台报告展示的细节,支持实时刷线报告,支持代码对比。通过对比可以我们详细看到文件变更的内容,以及便跟内容的覆盖率情况。

3.5.1 代码对比
那马可平台是如何做代码对比的呢?

我们借助了一个开源库,叫做 jsdiff,通过这个库我们可以对比出两个文件的差异信息。对比出来的结果是一个对象数组,这是个对象数组,数组包含 4 个内容:
count:行数;
Value:具体代码;
Added:是否新增;
Removed:是否删除。
通过解析这个数组,我们可以将对比的结果一一还原到页面中来,比如右下角,就是我们通过这个数组进行还原的结果。

四、总结规划
到这里我们对于马可代码覆盖率平台的技术方案,基本聊完了,对于马可代码覆盖率平台,我们接下来有两个比较大的规划。
1)一是丰富各端语言的接入:
前端包括小程序,Node.js,Typescript;
其他语言包括,Go,Java 等。
2)二是要做开源:
我们会将马可平台整体打包开源,拥抱开源社区,希望和大家一起共建马可平台。

上面就是我们对代码覆盖率的一些探索,代码覆盖率可以当做是测试质量的一个指标,提供了相对合理、客观的数据。但 100%的代码覆盖率,并不能代表 100%没有 bug,代码覆盖和用例是否正确没有一个明确的对应关系,仅仅是测试质量过程中的一个补充。不能盲目追求代码覆盖率,而应该想办法设计更多更好的用例,让用例和代码覆盖率相互补充,提升项目质量。
作者:vivo 官网商城前端团队-Song Jiachao
版权声明: 本文为 InfoQ 作者【vivo互联网技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/4fe981a052c7fed3b10c8707e】。文章转载请联系作者。
评论