前端精准测试是精准测试体系的一部分,但是由于前端项目比较灵活,各种框架,脚手架再加上开发同学写的不够规范,所以投入产出比较低,这部分内容在网上的资料也比较少。为了完善我们的精准测试体系,今年做了前端精准测试。精准测试的基础就是覆盖率,如何拿到覆盖率数据,生成覆盖率报告是核心。
一,覆盖率SDK的集成
前端覆盖率主要借助于istanbul (官方网站:https://istanbul.js.org )来实现的,而主要的插件有如下:
1,babel的前端工程
istanbul提供的babel插件babel-plugin-istanbul(https://github.com/istanbuljs/babel-plugin-istanbul) , 能够在代码编译打包阶段直接植入插桩代码 适用于使用babel的前端工程,基于react和vue的工程都可以。
(1)在package.json中添加插件
"babel-plugin-istanbul": "^6.1.1"
(2)在babel.config.js中添加
const plugins = []
//添加收集覆盖率插件
plugins.push(["babel-plugin-istanbul", {extension: ['.js', '.vue'],}])module.exports = {presets: ['@vue/app'],plugins
}
(3)检查覆盖率数据的生成
编译工程,访问前端项目页面,在控制台访问:window.__coverage__,如果有数据,则说明项目插入babel-plugin-istanbul成功。
2,vite前端工程
如果针对vite(https://vitejs.cn/)前端项目,按如下方法添加:
(1)在package.json中添加插件
"babel-plugin-istanbul": "^6.1.1"
(2)在vite.config.ts中添加:
plugins: [
// vite作为子应用接入qinakun在开发模式下需要把react()关掉
// https://github.com/umijs/qiankun/issues/1257
...(useDevMode
? []
: [
react(
mode === 'test'
? {
babel: {
plugins: ['babel-plugin-istanbul']
}
}
: undefined
)
]),
...
]
(3)检查覆盖率数据的生成
编译工程,访问前端项目页面,在控制台访问:window.__coverage__,如果有数据,则说明项目插入babel-plugin-istanbul成功。
注意:如果是通过vite完全生成的React项目,可以按如下方式进行配置:
(1)安装vite-plugin-istanbul插件:
地址:https://github.com/iFaxity/vite-plugin-istanbul
npm i -D vite-plugin-istanbul
or if you use yarn
yarn add -D vite-plugin-istanbul
(2) 配置vite.config.js
添加引用:
import istanbul from 'vite-plugin-istanbul';
添加插件配置
istanbul({
include:['src/*'],
extension:['.jsx']
})
最终的配置如下:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import istanbul from 'vite-plugin-istanbul';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(),
istanbul({
include:['src/*'],
extension:['.jsx']
})
],
})
启动项目,就可以得到覆盖率数据window.__coverage__
3,webpack前端工程
对于Webpack项目,需要使用另一个插件webpack-plugin-istanbul插件(https://github.com/smoosee/webpack-plugin-istanbul)
这个项目是最新发布的,显示 是五个月前提交的代码,所以要求:node版本大于16,webpack至少是5。
(1) 在项目中执行如下命令:
yarn add webpack-plugin-istanbul -D
(2)添加webpack配置
找到根目录下config/webpack.config.js文件,添加如下代码:
//覆盖率插件
const { WebpackPluginIstanbul } = require("webpack-plugin-istanbul");
//添加插件
plugins:[
new WebpackPluginIstanbul({
include: ["src/*.js","src/*.ts","src/*.tsx"],
exclude: ["src/**/*.spec.js"],
extension: [".js",".ts",".tsx"],
cwd: process.cwd(),
}),
...]
//在module中添加配置
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: "webpack-plugin-istanbul/loader",
options: {
include: ["src/*.js","src/*.ts","src/*.tsx"],
exclude: ["src/**/*.spec.js"],
extension: [".js",".ts",".tsx"],
cwd: process.cwd(),
},
},
},
...
]
}
注意:修改框架文档中给出的配置,默认只是js文件,我们添加上ts文件,tsx文件的相关配置。
(3)启动项目检测数据
做完上述配置后,启动项目,同样在控制台访问:window.__coverage__,如果有数据,则表明插件注入成功。
二,上传覆盖率数据
为了在精准测试平台上生成前端项目的覆盖率报告,需要将项目在本地产生的覆盖率数据上传到精准测试平台,这就需要使用我们提供的chrome插件。
1,上传覆盖率chrome插件
请下载下面的插件,安装到chrome上。覆盖率插件上传覆盖率数据逻辑如下所示:
添加完成后,如下所示:
注意:为了防止过渡采集数据,插件对网址进行过滤。
2,覆盖率数据上传
(1)安装完成插件后,刷新要测试的页面,将插件注入到页面中,等一分钟你可以从控制台看是否有如下输出,如果有,说明插件注入成功。
(2)打开插件,点击『开始上报』按钮,则会关闭插件,弹出数据采集浮层。如下所示:
-
请输入本次需求对应的Team任务的ID,然后才可以单击开始上报按钮。
-
如果停止上报,则会清除TeamID,此时可以切换ID或是重新输入。
-
如果要测试的内容没有teamID,则输入一下容易识别的英文字符串,在创建任务的时候把TeamID填写成一致的即可。
(3)开始进行测试
当看到弹层时,就可以执行具体的测试用例了,插件会一分钟自动上传一次覆盖率数据,控制台也会有输入,可以帮助你查看一下上传的情况。
你无需关注上传的数据,只管测试就行。
(4)结束覆盖率采集
当你测试完成后,可以打开插件,单击『停止上报』,关闭浮层,停止上报覆盖率数据。
三,生成覆盖率报告
覆盖率报告生成逻辑如下所示:
生成报告的核心逻辑如下:
-
下载项目源码到指定的目录中;
-
上传覆盖率数据到项目的.nyc_output目录中,并进行合并;
-
全并后生成全量报告,并生成合并后的覆盖率数据cov_merged.json文件;
-
根据git diff信息,过滤合并后地覆盖率文件,生成增量覆盖率数据;
-
对于合并覆盖率数据中没有的增量文件,则将相关的语句块,函数块,分支块等信息置空,以便在增量报告中展示出来。
-
生成增量报告。
-
在公司是通过精准测试平台来实现相关流程的串联的,在此就不展示平台操作了。
四,覆盖率报告解读
单击覆盖率任务名称,可以跳转到覆盖率分析记录页,可以看到本次报告的增量行覆盖率,全量行增开率和分支覆盖率,单击详情,可以看到更加详情的覆盖率数据。
单击『查看报告详情』,即可打开相应的覆盖率报告的结果,如下所示:
具体的覆盖率报告分析,可以参与文档:代码测试覆盖率分析: https://www.ucloud.cn/yun/84880.html
分析覆盖率的执行情况,可以看一下下面的文档,解读覆盖率报告的每一部分信息:
-
覆盖率报告解读:https://github.com/JChehe/blog/issues/49
注意以下几个重点:
1,四个测量维度
-
行覆盖率(line coverage):每个可执行代码行是否都执行了?
-
函数覆盖率(function coverage):每个函数是否都调用了?
-
分支覆盖率(branch coverage):每个流程控制的各个分支是否都执行了?
-
语句覆盖率(statement coverage):每个语句是否都执行了?
2,代码文件渲染解读
(1)“行覆盖率”中的行是指可执行代码行(Lines of Executable Code),而不是源文件中所有的行(含空行)——(Lines of Source Code)。
function doTheThing () // +0
{ // +0
const num = 1; // +1
console.log(num); // +1
} // +0
其中上面的函数中,可执行的行是2,而不是5。
-
import、声明都被视为非可执行行(+0),require、赋值等语句视为可执行行(+1)
-
如果某行存在可执行代码,则这一整行会被视为可执行代码行。
-
而如果一个语句被拆分为多行,则该可执行代码块中,仅第一行被会视为可执行行。
function func () { // +0
return { // +1
a: 1, // +0
b: 2, // +0
} // +0
} // +0
(2)测试覆盖率报告出现的标识
-
'E':'else path not taken',表示 if/else 语句的
if(含 else if)分支已测试,而 else 分支未测试。
-
'I':'if path not taken',与上面的 'E' 相反,即
if(含 else if) 分支未测试。
-
'Nx':表示当前可执行代码行被执行的总次数。
-
粉色(背景色):语句/函数未覆盖。
-
黄色(背景色):分支未覆盖。
注意:由于前端代码不像服务端代码那样,渲染的比较清楚,可以按上面的规则对覆盖率报告进行排查。后面如果我见到更加详情的报告解读,也会在些提供给大家的。