一, 前端精准测试架构介绍
今年从零开始完成了前端精准测试整体功能的开发,在基于istanbul插件的基础之间,实现覆盖率数据的采集,并根据服务端和移动端精准测试的整体架构,实现前端精准测试体系。整体架构及核心功能介绍如下:
l 覆盖率
-
借助于istanbul插件下的babel-istanbul-plugin, vite-istanbul-plugin和webpack-istanbul-plugin插件,对Vue,React项目实现插桩,进行覆盖率数据的采集;
-
利用chrome插件实现对覆盖率数据的定时上传,并在页面刷新,打开新页面,关闭页面和置于后台时等特殊场景实现覆盖率的上传;
-
利用nyc生成项目覆盖率数据全量,结合git diff过滤全量覆盖率数据生成增量报告的生成。
-
解决istanbul, nyc无法对diff代码,在完全没有执行的情况下生成覆盖率报告,以帮助业务同学查漏补缺;
l 调用链路分析
-
借助于ts-dependency-graph和dependency-cruiser,生成vue和react项目文件间的调用关系;
-
结合对项目源码的分析,解析出页面间的调用关系,脚本文件与页面间的调用关系,并在CCG服务上进行固化存储;
-
通过diff代码,结合CCG调用关系数据,开发前端精准测试链路分析功能;
-
通过分析项目源码,解析样式文件与页面的对应关系,通过CCG固化存储,以便分析项目样式文件的调用链路;
l 追溯关系
-
优化服务端关联用例Chrome插件,在关联服务端用例的同时,根据配置同时关联前端用例;
-
通过关联用例时,对用例执行时刷新页面,打开新页,关闭新页时覆盖率数据合并,生成整体用例完整的覆盖率数据;
-
解析用例对应的覆盖率数据,通过覆盖的页面文件,代码块,函数块,建立起用例与页面的关联关系,生成正向和逆向追溯关系。
l 用例推荐
-
通过git diff 分析出需求修改的代码文件列表,并解析出修改的行号;
-
通过调用链路,分析出脚本文件,样式文件影响到的页面文件;
-
通过需求修改的文件,行号,反查与文件关联的用例,再通过覆盖的语句块,函数块来过滤关联的用例;
-
对推荐出来的用例进行全面分析,根据用例的覆盖链路对用例去重,最后生成推荐用例列表;
l 全流程
-
结合链路分析,用例推荐,用例执行,覆盖率分析等功能,开发前端全流程功能;
-
根据推荐用例的结果,创建测试计划,在测试计划执行完成后,生成对应需求的覆盖率报告;
-
如果全流程执行过程中有覆盖率数据,则自动生成覆盖率报告,后续还可以手工生成覆盖率报告。
二,前端覆盖率
前端覆盖率相关的资料网上也有一部分,但是真正介绍清楚的不多。我们这边其他团队也做了一套东西,不过是开发主导的,一切从开发的角度出发,使用成本比较高。后来我们调研了相关资料,从测试角度出发,开发的前端覆盖率测试功能,主要包括以下三部分内容:
1,覆盖率数据采集
借助于istanbul插件下的babel-istanbul-plugin,vite-istanbul-plugin和webpack-istanbul-plugin插件,对Vue,React项目实现插桩,进行覆盖率数据的采集。这也是业界常规的做法,虽然我们也能看到其他的收集覆盖率的工具,但底层是一样的,封装的越多,使用越不灵活。
通过对前端项目进行插桩,项目打包部署后,访问页面的输出端window.__coverage__就可以得到当前页面操作的覆盖率数据,是JSON格式的数据。随着操作的执行,覆盖率数据会不断地变化。
2,覆盖率数据上传
对页面进行操作的时候,覆盖率数据是存储在浏览器的本地存储中的,刷新页面,关闭页面等操作会导致数据丢失。为了生成覆盖率报告,需要定时将数据上传到指定的服务器。
为了对被测对象产生最小的影响,我们采取chrome插件的方式,通过用户输入的域名,需求信息,自动收集浏览器的数据,定时把覆盖率数据上传到指定的服务器。同时在页面置到后台,页面刷新,页面关闭等特殊场景,也上传覆盖率数据,保证数据的完整性。整个插件的覆盖率上传控制逻辑如下所示:
3,覆盖率Agent
覆盖率其实就是完成一系列覆盖报告生成逻辑,其流程图在上面已经介绍。而istanbul插件的特性来分析一下得出,覆盖率数据为chrome浏览器加载的页面或是用户执行的页面的覆盖情况,是以json文件来记录覆盖的文件信息(文件路径,语句块起始位置,函数起始位置,分支起始位置),用户操作覆盖率的情况等。对于完全没有执行到的文件,是无法获取其覆盖率数据的。
l 全量报告的生成:将用户上传的覆盖率数据进行合并,nyc merge合并成一个文件,然后对合并后的json文件进行处理,主要是把文件中的文件路径替换成agent上项目源码的路径,否则报告中的代码文件无法渲染。替换完成后,使用nyc report生成覆盖率报告即可。
l 增量报告的生成:增量报告的生成有两个方案,一是,对增量文件进行插桩,然后生成报告,但是这样就无法生成全量报告;二是,通过git diff拿出增量文件以及修改的行,来过滤全量报告。本项目采取的是第二种方案,通过增量文件过滤全量覆盖率数据,然后根据更改的行号,处理覆盖的情况。另外,如果增量文件在全量报告中没有,就生成一个文件信息,语句块,函数块,分支信息都为空。这样生成的覆盖率报告中,对应的文件为灰色的,但是可以指导业务同学查漏补缺。
三,调用链路分析
前端调用和服务端,移动端的都不太一样,它没有明确函数级别的相互关联关系,对于脚本文件虽然有函数,但也不能分析函数与函数的调用关系,这是没有意义的。前端只能分析页面与页面,页面与组件,脚本文件与页面,样式文件与页面间的调用关系。从网上调研了一下,发现借助于ts-dependency-graph和dependency-cruiser,生成vue和react项目文件间的调用关系;但是要生成整体项目页面间的调用链路的话,还需要对数据做进一步的处理。
整体生成调用链路的流程图如下所示:
这个调用链路分析的粒度还是比较粗的,以页面为单位进行的分析,生成调用关系的时候,也是根据diff的文件,反查影响到的页面。这就会存在如下问题:
-
改动一个文件的部分页面,会分析出这个文件所有的调用链路,可能在影响范围外;
-
有可能脚本文件,样式文件无法对应到页面,评估不出其影响范围;
可以做的更加精细化一些,主要增加如下分析:
-
页面与组件间的调用关系,具体区分哪个是组件,组件改动的话,页面需要回归测试;如果页面改动,不影响组件的话,可以不测试组件;
-
脚本文件具体影响到页面的哪些行,以引用脚本文件中的函数行号为主,没有改动到相应的行号,则不用回归影响的页面;
-
样式文件也是同样的,分析具体引用样式文件中的函数的页面行号,这样就能将样式文件+函数,对应的具体的页面,减少影响范围。
如果做如上分析的话,可能会增加分析时间,需要在具体的项目中做出优化,此部分内容缺乏调试与调优。
四,追溯关系
前端关联用例的话,需要分析出用例执行过程中,对页面,脚本文件有执行覆盖情况,这样的信息在window.__coverage__中已经以json数据的格式展示出来,只需要解析出来进行保存。
1,用例关联插件
而追溯关系数据,必须从关联用例开始,为了减少业务同学的工作量,在关联用例的时候前后端用例同时进行关联,所以优化服务端关联用例插件,核心逻辑如下所示:
这里面存在以下问题:
-
一个用例操作过程中,可能会包括各种状态:页面刷新,打开新页面,关闭页面或是结束用例录制等;
-
一个用例只有要状态变化,就上传覆盖率数据,这就会产生一个用例对应多个覆盖率数据文件的情况;
-
通过需求ID和用例ID来区分用例对应的覆盖率数据。
2,用例覆盖率解析
当用例对应的覆盖率文件上传到精准测试平台后,需要解析一下用例对代码的覆盖情况,用例解析流程如下:
注意以下几个要点:
-
用例解析前,需要把一个用例对应的所有覆盖率文件进行合并,然后再解析,否则会造成数据的丢失;
-
目前解析的是用例影响到的页面文件tsx,vue文件,没有记录脚本文件,其实也可以保存脚本文件的覆盖情况;
-
解析覆盖情况时,取用例覆盖文件的语句块,函数块,而不是具体的代码行;后面可以调研一下,能否精确到代码行;
-
istanbul插件无法对样式文件进行插桩,所以也没有样式文件的覆盖情况,这个需要业务同学自行确认。
五,用例推荐
前端用例推荐和服务端,移动端原理上是类似的,就是推荐出本次需求改动的代码,影响到的代码需要回归的测试用例;但是核心算法又不相同,没有办法使用圈复杂度,函数行号等一系列数据指标进行计算用例分数,目前前端精准测试用例推荐流程如下所示:
当前的推荐策略完成了如下功能:
-
通过diff代码,拿到需求修改的文件列表和行号列表;
-
通过对文件进行过滤,分情况查询用例,查询调用关系,过滤函数;
-
过滤函数是通过行号是否在用例关联的页面的语句块,函数块内,如果在则选择函数,不在则放弃;
-
粒度有点儿粗,暂时还没有其他的算法,在后面业务使用过程中,再逐步细化,添加相应的算法进行筛选。
六,全流程
整个的核心思想就是提供各个可单独使用的功能模块,又有串起各个模块的全流程,一键化操作。和移动端不同的是,前端没有处理istanbul插件自动注入功能,因为前端框架,脚手架太多,没有办法自动注入,此功能就由开发同学来完成。所以前端精准测试全流程包含:链路分析,用例推荐,用例执行,覆盖率分析等核心流程。
1,全流程流程图
现在的全流程功能的流程如下图所示:
将所有单独的功能串联起来,实现一键化执行所有流程。注意每个环节都要添加上循环检测执行过程,由于前端全流程没有打包环节,执行速度还是非常快的。
2,全流程功能分析
现在全流程基本功能没有问题,主要有两个核心数据需要完成。
(1)用例与代码关联
所有推荐的基础就是用例与代码的关联,然后再通过一系列关联推荐算法,让用例越来越精准。所以关联用例是前提的,需要业务同学在使用过程中,不断在关联手工测试用例与相应的代码,只有建立了这个关系,才能更好地推荐。
(2)推荐算法优化
当前的推荐算法只是查询,针对于前端用例,由于在录制过程中业务同学对录制的时机可能掌握的不够好,录制的操作步骤有前置或是后置操作,这就造成了一个用例与非常多的代码有关联,推荐的时候不太好过滤,这就造成了推荐用例过多的情况。
(3)用例关联的细化
现在用例关联的时候,只关联了用例覆盖的页面的覆盖率数据,对于脚本文件没有存储其覆盖的情况,推荐的时候通过脚本文件查询影响的页面,进而推荐,粒度有点儿粗,后面需要细化一下。
增加样式文件的调用链路分析和用例推荐,由于istanbul没有办法对样式文件进行注入,所以覆盖率数据是拿不到样式文件信息的。我们可以过滤一下项目的源码,解析出样式文件与页面文件的关系,再分析页面文件,找到样式文件影响到的页面文件行号,进而细化其影响面,生成调用有关系和推荐数据的时候过滤用例。
七,总结
现在前端精准测试整体功能已经开发完成,覆盖率已经在几个业务线进行使用,通过分析覆盖率增量报告,查找遗漏的地方,再补充用例提高覆盖范围。经业务同学反馈,效果明显,通过覆盖率也增加了测试的信心。
其他环节有待在各个业务线进行使用,主要是要关联测试用例,这个是整个精准测试的基础,后面在使用中,逐步对业务中的特殊场景,不规范的编码进行兼容,同时优化用例推荐算法,以实现以最小的测试用例集达到最大的测试覆盖,以提高测试效率。