开源覆盖率项目分享----从插桩到看板:一套覆盖率采集与分析工具
构建测试覆盖率上报平台:让质量度量可视化
在快速迭代的研发流程中,我们常常面临这样的灵魂拷问:“这次上线的代码,测试真的覆盖全了吗?”、“核心业务逻辑有没有漏测?”、“哪些是无效测试?”
传统的覆盖率统计往往依赖人工跑脚本、导出报告、合并数据,流程割裂且滞后。为了解决这些痛点,近期自研了一套自动化测试覆盖率上报平台。本文将分享该平台的架构设计与实现细节,希望能给同样在探索质量效能的同学一些参考。
增量覆盖率详情:
全量覆盖率详情:
覆盖率数据上报:
一、这套系统在解决什么问题
前端单测之外,很多团队还希望掌握真实运行环境下的语句 / 分支覆盖。常见路径是:
- 在 Vite 或 Webpack 构建链路里打开 Istanbul 插桩,在浏览器里维护
window.__coverage__; - 由页面脚本周期性 POST 到服务端,与 Git 分支、commit、项目标识 绑定后落库;
- 在管理界面里按项目 / 测试分支查看报告、对比增量、必要时做人工标记(冗余行、兜底代码、插桩排除等)。
cover-code monorepo 把上述链路拆成四块(关系详见docs/模块关系说明.md) 与 (docs/PROJECT.md)):
| 部分 | 职责 |
|---|---|
SDK(sdk/) | 在业务工程里插桩 + 可选上报脚本 |
| cover-admin 后端 | 接收覆盖率、鉴权、项目 / 任务 / 报告数据 |
| cover-admin-front | Vue 管理端:项目、全量 / 增量任务、详情弹窗等 |
| examples | 本地联调 demo、简易接收服务 |
二、SDK:在业务项目里接入
SDK 由多个 npm 包组成,业务侧通常只直接依赖构建插件之一;二者都依赖 istanbul-live-core 生成上报逻辑。
| 包名 | 场景 |
|---|---|
istanbul-live-vite-plugin | Vite 5/6 + vite-plugin-istanbul |
istanbul-live-webpack-plugin | Webpack 5 + 自定义 istanbul-loader |
istanbul-live-core | 一般由插件间接依赖;自研上报时可单独用 |
istanbul-live-babel | 非 Vite/Webpack 标准链时的 Babel 单段插桩辅助 |
2.1 与管理系统对齐的两个关键配置
-
project_code(插件侧)
必须与管理后台里该项目的code(项目编码) 一致。服务端接收上报时,会用请求头X-Project-Code(由 SDK 从project_code映射)去匹配branch_coverage等配置。 -
upload.endpoint
指向管理后端的POST /api/coverage/upload(公开接口,无需 JWT)。
2.2 Vite 配置
在 vite.config 里展开插件数组,并用环境变量控制是否开启覆盖率(示例见 examples/vite-vue3/vite.config.js):
import { istanbulLiveVitePlugin } from 'istanbul-live-vite-plugin'
export default defineConfig({
plugins: [
vue(),
...istanbulLiveVitePlugin({
coverage: true, // 或由 mode / loadEnv 计算
project_code: '与你的项目 code 一致',
upload: { endpoint: 'http://127.0.0.1:3000/api/coverage/upload' //上报地址 },
// 其余 include/exclude 等与 vite-plugin-istanbul 一致
}),
],
})
更细的参数、Vue 模板插桩、optimizeDeps.exclude 等见 (sdk/vite-plugin/README.md)。
2.3 Webpack 配置
使用 IstanbulLiveWebpackPlugin,由 coverage: true 开启;需 html-webpack-plugin 才能注入上报脚本(示例见 examples/webpack-react-ts/webpack.config.cjs):
const { IstanbulLiveWebpackPlugin } = require('istanbul-live-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({ template: 'index.html' }),
new IstanbulLiveWebpackPlugin({
project_code: '与你的项目 code 一致',
coverage: true,
upload: { endpoint: 'http://127.0.0.1:3000/api/coverage/upload' //上报地址},
}),
]
Source Map、源码目录不在 src 时的 instrumentRoots 等见 sdk/webpack-plugin/README.md
三、安装与运行管理系统
管理系统 = NestJS 后端(apps/cover-admin)+ Vue 前端(apps/cover-admin-front)
3.1 依赖服务:MySQL 与 Redis
后端使用 MySQL 8 持久化、Redis 管理登录态(Access / Refresh Token)。在 apps/cover-admin 目录:
- 创建数据库(名称与账号以你环境为准,README 中有示例账号说明)。
- 执行建表脚本:
mysql -u <user> -p <db_name> < apps/cover-admin/database/schema.sql
- 启动 Redis(若配置了
requirepass,需与.env一致)。
3.2 后端环境变量与启动
cd apps/cover-admin
copy .env.example .env # Windows;Linux/macOS 用 cp
# 编辑 .env:数据库、Redis、PORT 等
pnpm install
pnpm run start:dev
默认监听端口以 .env / main.ts 为准(文档中常见示例为 3001,亦有 3000,以你本机为准)。
3.3 前端环境变量与启动
在仓库根目录:
pnpm install
在 apps/cover-admin-front 配置 VITE_API_BASE_URL 指向后端根(如 http://127.0.0.1:3001),与后端 PORT 一致。
pnpm run dev:admin
浏览器访问 Vite 提示的本地地址,使用 POST /api/users/register 注册的首个账号登录;菜单与按钮受 RBAC / UI 权限 控制,若看不到「项目管理」等菜单,需在后台为角色分配对应接口与菜单权限(详见 apps/cover-admin/docs/API.md 权限表)。
生产构建:
pnpm run build:server
pnpm run build:admin
四、如何添加「项目」
项目是 Git 仓库维度的元数据:名称、唯一 code、仓库地址、主分支、相对目录、可选 Token 等。后续 SDK 的 project_code、上报路由匹配,都依赖这里的 code。
4.1 在界面中操作
- 登录管理端。
- 打开 「项目管理」(路由一般为
/report/project)。 - 点击 新建,填写表单:
- 项目名称、项目 code(全局唯一,建议与仓库或业务线约定一致);
- Git URL、主分支(如
main/master); - 相对路径:覆盖率路径相对仓库根的路径(与上报文件路径对齐,增量对比等逻辑会用到);
- 仓库 Token(私有仓库拉 raw / 对比时可能需要;编辑时留空通常表示不修改已存 Token)。
- 保存后,项目会出现在列表与后续「覆盖率任务」的项目下拉框中。
五、「覆盖率任务」创建
同一 projectId + testBranch 下,全量与增量各至多一条任务(两种 scope 可并存两条记录)。创建接口为 POST /api/branch-coverages/create,body 含 projectId、testBranch、taskScope。
5.1 在界面中创建
- 确保已完成上一节的 项目 创建,并记下
project_code(即项目code)。 - 打开 「全量覆盖率管理」 或 「增量覆盖率」。
- 点击 新建,选择项目、填写 测试分支(与 CI / 本地运行应用时的 Git 分支一致,或与上报头
X-Git-Branch能对上的命名习惯)。 - 保存后,列表中会出现该任务;浏览器/SDK 上报时,服务端根据
X-Project-Code+X-Git-Branch(及库内配置)把数据归入对应任务下的coverage_report。
5.2 运行插桩应用并验证
- 业务工程里将
project_code设为该项目code; upload.endpoint指向当前环境的/api/coverage/upload;- 启动应用,打开页面,等待若干上报周期;
- 回到管理端对应任务,查看上报列表 / 打开 覆盖率详情 弹窗(含文件树、源码、人工标记等)。