前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端精准测试探索:覆盖率实时统计工具

前端精准测试探索:覆盖率实时统计工具

作者头像
有赞coder
发布2020-08-25 15:37:16
1.8K0
发布2020-08-25 15:37:16
举报

背景

随着业务增长,随之而来的前端需求激增,如何在有限的时间内保证前端代码的质量。通过测试同学单方面的保障,还是免不了前端线上问题,存在回归不到位或者测试遗漏的地方,同时测试质量的高低没有客观数据可量化。

通过单测方法补充,可以提前发现一部分问题,减少问题解决的成本,但是由于业务形态的原因, 需求变更频繁,功能迭代快,补充和维护单测的成本比较高, 在业务方的大部分前端工程中暂时没有单测方法,因此开发在自测时, 感知比较薄弱,无量化数据, 在项目提测前也没有统一指标可以把关,测试对开发的自测状况也不了解。

同时前端缺少像 jacoco 这样的集成测试覆盖率统计框架,无法通过集成测试收集覆盖率,对于测试阶段的质量仍然没有数据量化。

结合上面说的几点,我们提出了前端集成测试覆盖率统计工具的需要,以此来提升开发自测质量以及项目提测质量,同时帮助补充回归不到位或测试遗漏的场景,提升上线质量。

一、技术选型

首先,覆盖率收集的前提,需要完成代码插桩工作,插桩方法来自于两个开源覆盖率统计框架,istanbul.js以及istanbul-middleware (以下称im),提供了若干个插桩方法,而 im 其实也是在 istanbul.js 的基础上做了封装, 能力来自于 istanbul-lib-instrument 所有的插桩方法,大致分为两种类型:

  • 运行前插桩
  • 运行时插桩
1.1 运行前插桩

nyc instrument 针对编译之后的JS文件 , 进行手动插桩 , 形成插桩后的新JS文件。 babel-plugin-istanbul istanbul提供的babel插件 , 能够在代码编译打包阶段直接植入插桩代码。适用于使用babel的前端工程,基于react和vue的工程都可以。

1.2 运行时插桩

im.hookLoader:适用于服务端的文件挂载 比如 node 应用。

当应用启动时,会在 require 入口处添加 hook 方法,使得应用启动时加载到的都是插桩后的代码。 im.createClientHandler:适用于客户端的 JS 挂载,比如 react 和 vue 的 js。

通过指定 root 路径,会把所有该路径的js文件请求拦截,返回插桩后的代码,即浏览器请求静态资源的动作。效果与 babel-plugin-istanbul 类似,区别在于该方法是在浏览器请求js时才会返回插桩代码,是一个动态过程。

插桩方式

功能

优势

劣势

nyc

本地手动插桩源js文件, 生成插桩后文件

编译后的js都可手动插桩, 不限工程框架

手动插桩后的文件需要自己上传, 对原打包发布流程有影响; 不适用于服务端插桩

babel-plugin-istanbul

在babel编译时 , 自动生成插桩代码

改造成本低 , 自动插桩快捷

限定于使用babel的工程

im.hookLoader

require入口处添加钩子方法,返回已插桩代码

改造成本低 , 自动插桩快捷

仅适用于服务端插桩

im.createClientHandler

拦截浏览器请求静态资源文件的GET方法, 返回插桩后的JS

自动插桩 , 无须改造原打包流程和脚本

仅适用于客户端插桩; 该方法基于express, 限定于使用express的工程

最后我们所使用的插桩方法:

App(node)—— istanbulMiddleware.hookLoader Client(react & vue)—— babel-plugin-istanbul

二、模块设计

主要分为三个模块,先通过代码插桩获得可追踪的代码,然后实时上报用户行为产生的代码行覆盖记录,最后呈现覆盖率相关信息。

2.1 代码插桩

Client端:使用babel-plugin-istanbul插件,在babel编译阶段即可完成。

Node端:依赖istanbuljs提供的能力 - istanbul-lib-hook 、istanbul-lib-instrument 重写istanbulMiddleware.hookLoader方法,node启动前挂载文件,会在require方法前增加钩子函数,增加代码插桩。

插桩结果举例:

被插桩的 JS 会新增一个 coverage 方法,维护并指向覆盖率信息归属,并用来获取该文件的覆盖率信息。

同时该 JS 中的方法在执行过程的路径上会留下标记,被执行到之后实时更新覆盖率信息中相对应的行或者块信息。

2.2 数据上报

Node端:应用发布时,写入对应的工程和分支信息,创建定时器,实时上传_global.coverage变量,即覆盖率信息。

Client端:客户端的上报比较特殊,客户端不像服务端,在发布后可以全局保持coverage变量以及定时器方法,client端所有的数据生成和消耗都跟随页面的生命周期,所以不太可控,因此需要一个额外容器进行处理,我们选择了通过chrome插件来上报,通过全局管理覆盖率信息对象,以及通知下发来实现上报流程。该插件详细的工作流程如下:

覆盖率服务端

  • 继承istanbul middleware的功能
  • 支持分支维度接收和查询覆盖率
  • 代码变更时覆盖率替换, 支持存储和查看历史版本

主要基于istanbul-middleware做了二次开发,扩展了istanbulMiddleware.createHandler方法:

/:ns/:repo /:ns/:repo/show

两个覆盖率展示接口,新增了ns、repo、branch三个入参,用来区别不同的覆盖率 同时增加额外参数history 传入该变量,标志获取的是历史覆盖率。

/client/:ns/:repo?branch={}&source={} body

携带覆盖率信息,根据应用和分支信息上报,接收到上报信息之后,会先获取该分支下的已有覆盖率,然后和此次上报的信息做合并。

合并是根据文件名字遍历合并的。如果发现某个文件新旧两份覆盖率结构不同,即发生了代码变更,则会丢弃旧的覆盖率,以新覆盖率为准,同时把旧的覆盖率存储到历史版本中。

2.3 页面展示

全量覆盖率展示:使用istanbulmiddle原生报告生成。

增量覆盖率展示:通过gitlab接口对比master差异,分文件展示各自的覆盖率,同全量覆盖率,只是细化了,整体页面用vue + muse-ui完成。

以master分支为基准, 增量文件覆盖率

全量文件覆盖率目录结构


三、工作流程

主要分为3部分:对应上一节说的接入 、上报 、展示。

通过babel插件完成客户端代码插桩,提供给node端使用的插桩插件,可以一步完成服务端的代码插桩以及定时上报功能。

配合提供的chrome插件,完成客户端的覆盖率上报任务。

覆盖率服务端负责信息的接收和存储,并返回给前端数据信息。

前端负责数据信息展示。

四、业务实践

接入测试环境发布平台,实现以应用和分支维度的多版本实时覆盖率收集和展示功能,无缝对接项目测试环境,项目中各应用发布后,自动开启覆盖率上报,在项目测试过程中实时记录,可实时查看。在项目提测前,给予开发量化指标,项目测试结束后可以给出最终覆盖率数据,帮助测试同学检查以及完善未覆盖的功能。

目前在电商教育和行业两条业务线中已有接入,由于该工具限制在qa环境使用,仅限收集在qa环境测试的项目数据。 在功能测试阶段,从使用数据上来看,增量行代码覆盖率达到80%以上(目前的增量只到文件维度 ,未到行维度),未覆盖的行主要包括四种: 异常捕获、防御性编码、非本次新增无需关心的代码以冗余代码,属于可允许的范围。

-The End-

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有赞coder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 一、技术选型
  • 二、模块设计
    • 2.1 代码插桩
      • 2.2 数据上报
      • 三、工作流程
      • 四、业务实践
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档