尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Huly.server 代码覆盖率实战指南:LCOV 合并、HTML 报告与全量测试工作流解析

Huly.server 代码覆盖率实战指南:LCOV 合并、HTML 报告与全量测试工作流解析 Huly.server 代码覆盖率实战指南LCOV 合并、HTML 报告与全量测试工作流解析【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform本文以foundations/serverhuly.servermonorepo 中的覆盖率脚本目录为核心完整讲解其四个 Node.js 覆盖率工具合并 LCOV、生成 HTML 报告、展示汇总、批量跑测试的用法、实现原理与依赖关系并结合仓库中的 Jest 配置与 Rush 工作流给出可直接落地的覆盖率采集、汇总与 CI 集成方案。读完本文你将能在多包 monorepo 中一键生成合并后的覆盖率报告、按包查看覆盖率汇总并理解其底层数据流。一、脚本目录概览huly.server 的覆盖率工具集foundations/server是基于 Rush pnpm 管理的多包服务端 monorepohcengineering/*系列包其覆盖率相关脚本集中放在 foundations/server/common/scripts 目录下。根据 foundations/server/common/scripts/README.md 的定位说明该目录中的 Node.js 脚本专门负责 huly.server monorepo 的代码覆盖率管理工作解决多包场景下每个包各自产出覆盖率文件、却难以整体评估的痛点。目录内包含四个核心 Node.js 脚本及两个遗留 bash 脚本脚本作用输入 → 输出merge-coverage.js合并各包 LCOV 报告为单一 LCOV 文件packages/*/coverage/lcov.info等 →coverage/lcov.infogenerate-coverage-html.js由 LCOV 数据生成交互式 HTML 报告coverage/lcov.info→coverage/html/show-coverage-summary.js按包展示覆盖率汇总表格coverage/lcov.info→ 终端表格run-tests-with-coverage.js依次运行所有包的测试并采集覆盖率各包npm test→ 终端汇总该目录自身的package.json声明为hcengineering/scripts私有包shouldPublish: false见 foundations/server/rush.json并作为 Rush 工程清单中的一个项目projectFolder: common/scripts被管理因此其依赖lcov-parse、istanbul-lib-coverage、istanbul-lib-report、istanbul-reports也通过 Rush 统一安装与仓库其他包共享 pnpm 依赖树。二、merge-coverage.js把零散 LCOV 合并成一份全局报告多包 monorepo 中每个包运行 Jest 后会在各自目录下生成coverage/lcov.info。merge-coverage.js的作用正是把这些零散报告合并为仓库根目录下的单一coverage/lcov.info为后续生成 HTML 或上传 CI 提供统一输入。用法node merge-coverage.js核心流程对应 merge-coverage.js 源码扫描候选目录L5-L16硬编码[packages, pods, tests]三个目录逐个检查packages/name/coverage/lcov.info、pods/name/coverage/lcov.info、tests/name/coverage/lcov.info是否存在。若一个都找不到则输出错误No lcov files found in packages/pods/tests/*/coverage/lcov.info并以退出码 1 终止。构建仓库文件索引L29-L53以node_modules、.git、coverage、lib、dist、types、.rush、temp、pnpm-store为忽略目录递归收集仓库内全部源文件路径供后续 SFSource File路径匹配使用。逐文件合并并处理 LCOV 记录TN 头去重L62-L68LCOV 中TN:test name行在合并后只需保留一条脚本用seenTN标志跳过重复的 TN 头SF 路径解析L70-L98对每条SF:记录的源文件路径做四级解析——若为绝对路径且存在则原样保留否则以包目录为基准解析为绝对路径再尝试仓库文件索引的后缀匹配最后全部失败才保留原始路径。写出结果合并内容写入coverage/lcov.info并在终端打印Merged n lcov files into path。这种先建立仓库文件索引、再多级回退解析 SF的设计正是为了应对各包 LCOV 中源路径写法不一致相对/绝对/缺失前缀的问题是合并脚本最值得借鉴的实现细节。三、generate-coverage-html.js生成逐行覆盖的交互式 HTML 报告合并完 LCOV 后generate-coverage-html.js负责把它渲染成人类可读的 HTML 报告。用法node generate-coverage-html.js [input-lcov-file] [output-directory] # 默认用法源码 L5 的默认参数值 node generate-coverage-html.js coverage/lcov.info coverage/html核心流程对应 generate-coverage-html.js 源码输入校验L7-L10输入 LCOV 文件不存在时立即报错退出。LCOV 解析L41-L45使用lcov-parse把 LCOV 文本解析为结构化对象每个文件条目包含file、lines、functions、branches等字段。构建 Istanbul 覆盖率地图L47-L73用istanbul-lib-coverage的createCoverageMap创建空地图再为每个文件构造statementMap/fnMap/branchMap。由于 LCOV 的DA:line hit数据是按行的脚本将每行数据合成一条 statement 记录{ start: { line, column: 0 }, end: { line, column: 0 } }命中次数取自d.hit从而让 Istanbul 能把行覆盖渲染到报告上。自定义 sourceFinderL75-L104报告渲染时需要读取源文件内容以展示未覆盖的行脚本实现了三级查找策略——绝对路径直读 → 仓库根目录相对路径直读 → 仓库文件索引后缀匹配仍未命中的路径会被记录进__unresolved集合用于调试。生成 HTMLL106-L112通过istanbul-lib-report的createContext与istanbul-reports的html报告器输出到目标目录。HTML 后处理修复源码缺失L113-L152遍历解析出的每个文件若对应 HTML 页面包含Unable to lookup source占位符则尝试再次解析源文件将源码 HTML 转义后替换pre classprettyprint ...代码块从而修复报告中看不到源码的问题。输出产物coverage/html/index.html— 汇总报告主页coverage/html/**/*.html— 各文件的逐行覆盖详情页。依赖说明与 package.json 的 devDependencies 一致lcov-parse— 解析 LCOV 格式istanbul-lib-coverage— 覆盖率数据地图管理istanbul-lib-report— 报告上下文与渲染管线istanbul-reports— 具体的 HTML 报告生成器。四、show-coverage-summary.js按包输出覆盖率汇总表格在终端快速查看哪个包覆盖了多少行是日常开发的高频操作show-coverage-summary.js正是为此设计。用法node show-coverage-summary.js [lcov-file] # 默认读取合并后的全局报告 node show-coverage-summary.js coverage/lcov.info核心流程对应 show-coverage-summary.js 源码参数与文件校验L11-L18支持绝对或相对路径文件不存在时打印Error: LCOV file not found并退出。解析 LCOVL32-L53遍历每一行SF:建立当前文件条目DA:记录行数total命中数大于 0 则covered同时从路径中提取packages/pkg段作为包名归属L38-L43。按包聚合L56-L68以包名为键累加total/covered并按包名字母序排序。输出表格L70-L102打印对齐的Package | Covered | Total | Coverage表格并汇总输出整体TOTAL行。示例输出原文档给出的运行效果 COVERAGE SUMMARY BY PACKAGE Package Covered Total Coverage ---------------------------------------------- datalake 10 10 100.00% minio 111 165 67.27% postgres 815 1351 60.33% ... ---------------------------------------------- TOTAL 1156 2220 52.07%表格末尾还会提示 HTML 报告与合并 LCOV 文件的存放位置coverage/html/index.html与传入的 lcov 路径。五、run-tests-with-coverage.js批量运行全部包的覆盖率测试当需要逐个验证每个包的测试与覆盖率时run-tests-with-coverage.js提供了比rush test更细粒度的逐包执行方式。用法node run-tests-with-coverage.js核心流程对应 run-tests-with-coverage.js 源码扫描包目录L23-L27读取packages/下所有目录并按字母排序逐包判定可测性L29-L40跳过没有package.json或没有scripts.test的包依次执行测试L45-L89通过child_process.spawn运行npm test -- --coverage --silent注意 L46 针对 Windows 使用npm.cmd并解析 stdout 中Coverage summary区块的 Statements/Branches/Functions/Lines 行实时打印stderr 被忽略以保持输出整洁汇总结果L92-L111串行await 循环跑完所有包后打印Tested n packages并列出退出码非 0 的失败包清单。脚本对每个包依次等待for ... of await避免并发执行带来的资源竞争适合在本地或 CI 上获取逐包状态。原文档明确说明这是rush test的替代方案用于逐个包运行测试。六、NPM 脚本别名一键唤起四个工具foundations/server/common/scripts/package.json 为上述脚本提供了便捷别名# 合并覆盖率报告 npm run coverage:merge # 生成 HTML 报告 npm run coverage:html # 展示覆盖率汇总 npm run coverage:summary # 运行所有包的覆盖率测试 npm run test:coverage其中coverage:html已预设参数coverage/lcov.info coverage/htmlcoverage:summary也默认读取coverage/lcov.info与各脚本的默认值完全对齐。由于该包由 Rush 管理在仓库根目录执行rushx如rushx coverage:merge也可以触发同名脚本。七、完整覆盖率工作流从测试到报告的两种姿势方式一Rush 一键命令推荐# 运行所有测试并生成覆盖率报告 rush coverage该命令内部依次完成三件事原文档说明rush test— 运行所有包测试Jest 已默认开启覆盖率采集node scripts/merge-coverage.js— 合并所有包的 LCOV 文件node scripts/generate-coverage-html.js— 生成 HTML 报告。方式二手动分步执行# 1. 运行测试并采集覆盖率jest.config.js 已默认开启 rush test # 2. 合并各包覆盖率报告 node common/scripts/merge-coverage.js # 3. 生成 HTML 报告 node common/scripts/generate-coverage-html.js coverage/lcov.info coverage/html # 4. 查看按包汇总 node common/scripts/show-coverage-summary.js说明foundations/server是独立于仓库其他部分的 Rush 工程有自己的 foundations/server/rush.json上述rush命令应在foundations/server目录下执行。Rush 版本为 5.158.1pnpm 版本为 10.15.1见 rush.json。八、Jest 配置覆盖率为何开箱即用README 中给出的通用jest.config.js模板与仓库内各包的真实配置完全一致。以 foundations/server/packages/core/jest.config.js 为例module.exports { preset: ts-jest, testEnvironment: node, testMatch: [**/?(*.)(spec|test).[jt]s?(x)], roots: [./src], collectCoverage: true, // 默认开启覆盖率采集 coverageReporters: [text-summary, html, lcov], // 同时产出文本摘要、HTML、LCOV coverageDirectory: coverage // 输出目录 }三个关键配置项的作用collectCoverage: true— 无需在命令行加--coverage也会采集覆盖率run-tests-with-coverage.js中仍显式传入--coverage是为了双保险coverageReporters: [text-summary, html, lcov]—lcov报告器产出的正是合并脚本需要的coverage/lcov.infotext-summary则供run-tests-with-coverage.js提取 Statements/Branches/Functions/Lines 摘要coverageDirectory: coverage— 各包输出目录统一为包目录下的coverage/这正是merge-coverage.js扫描路径packages/name/coverage/lcov.info成立的前提。仓库内packages/client、packages/collaboration等包的 jest.config.js 均采用相同结构可横向参照。九、输出文件结构一次完整覆盖率流程后仓库会产生如下结构coverage/ ├── lcov.info # 合并后的全局 LCOV 数据 └── html/ # HTML 报告 ├── index.html # 汇总报告主页 ├── base.css # 样式 ├── prettify.js # 代码高亮 └── [package]/ # 各包报告 └── [file].html # 各文件逐行覆盖详情 packages/ └── [package-name]/ └── coverage/ ├── lcov.info # 该包自身的 LCOV └── html/ # 该包自身的 HTML十、覆盖率阈值参考README 中给出了当前整体覆盖率52.07%及按包分级目标可作为质量门禁的参考基准区间评价≥90%优秀Excellent coverage70–89%良好Good coverage50–69%中等需改进Moderate coverage50%较低优先改进Low coverage十一、故障排查报错No lcov files found in packages/pods/tests/*/coverage/lcov.info原因merge-coverage.js扫描不到任何 LCOV 文件。 解决先执行rush test生成覆盖率文件再运行合并脚本。报错Cannot find module lcov-parse原因脚本依赖未安装。 解决cd common/scripts npm install或通过 Rush 统一安装在foundations/server下执行rush update/rush install。HTML 报告中找不到源码generate-coverage-html.js的 sourceFinder 依次尝试绝对路径直读 → 仓库根目录相对路径 → 仓库文件索引后缀匹配generate-coverage-html.js并在渲染后对仍含Unable to lookup source占位符的页面做源码回填修复。若仍缺失请检查 LCOV 中 SF 路径是否正确、源文件是否真实存在。十二、遗留 bash 脚本与新脚本的对比目录中的两个 bash 脚本为旧实现已由 Node.js 版本取代show-coverage.sh→run-tests-with-coverage.jsshow-coverage-summary.sh→show-coverage-summary.js从源码对比可见升级动因show-coverage.sh依赖grep -A 4 Coverage summary逐包抓取文本跨平台Windows能力弱show-coverage-summary.sh用awk解析 LCOV 并按包聚合逻辑与 JS 版一致show-coverage-summary.sh但维护成本更高。bash 版本仅为向后兼容保留推荐使用 Node.js 版本以获得更好的跨平台支持与可维护性。十三、CI/CD 集成LCOV 与主流覆盖率工具合并出的全局coverage/lcov.info是标准 LCOV 格式可直接对接常见覆盖率平台Codecov通过官方 bash 上传脚本推送coverage/lcov.infoCoveralls通过cat coverage/lcov.info | coveralls管道上传SonarQube在 sonar 配置中设置sonar.javascript.lcov.reportPathscoverage/lcov.info即可让 SonarQube 读取合并后的 LCOV 数据。这意味着rush coverage或手动三步产出的coverage/lcov.info可以直接嵌入 CI 流水线无需为不同平台单独实现上传逻辑。配合前文的覆盖率阈值分级还可以在 CI 中加入覆盖率门禁把按包覆盖率作为质量红线。十四、延伸阅读脚本目录与文档foundations/server/common/scripts/README.md合并脚本实现foundations/server/common/scripts/merge-coverage.jsHTML 报告生成foundations/server/common/scripts/generate-coverage-html.js汇总与批量测试foundations/server/common/scripts/show-coverage-summary.js、foundations/server/common/scripts/run-tests-with-coverage.js脚本包清单与别名foundations/server/common/scripts/package.jsonJest 覆盖率配置示例foundations/server/packages/core/jest.config.jsRush 工程清单含hcengineering/scripts项目登记foundations/server/rush.json备注原文档See Also中引用的COVERAGE_REPORT.md完整覆盖率分析报告在当前仓库中未检索到若需深度覆盖率分析可基于coverage/lcov.info结合本目录工具自行生成。【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表