无内置单测/E2E的Angular v10应用如何通过外部测试套件获取代码覆盖率
需求可行性判定
该需求完全可落地。你之前尝试执行nyc ng serve触发编译失败的核心原因是场景适配方向错误:nyc/istanbul在纯Node应用场景下的工作逻辑是在Node进程侧拦截代码加载、完成运行时插桩,但Angular应用的业务代码最终是编译为浏览器端JS在客户端运行的,强行在Node侧套nyc包裹Angular的构建命令,既会打乱Angular的webpack编译流程,也无法正确在前端运行时生成统计埋点,自然无法生成可正常访问的应用。
适配Angular v10的完整实现路径
- 利用Angular官方内置的istanbul插桩能力完成打包
不需要额外引入第三方插桩工具,Angular v10的构建链路已经原生集成了istanbul插桩能力,只需要修改项目根目录下的angular.json配置,在对应项目的build目标选项中开启codeCoverage开关即可:
这个配置会在前端代码打包阶段自动给所有业务源码(组件、服务、工具类helper、管道、指令等)注入istanbul的统计埋点,生成可在浏览器环境正常运行的代码包,不会触发编译失败的问题。"architect": { "build": { "options": { "codeCoverage": true, "sourceMap": true, // 可按需配置排除无需统计的路径 "codeCoverageExclude": [ "src/**/*.spec.ts", "src/assets/**/*" ] // 保留原有其他配置不动 } } } - 启动带埋点的本地服务
直接执行常规的ng serve命令启动服务即可,不需要在外层包裹nyc命令。此时打开应用页面,浏览器全局环境中会自动生成window.__coverage__对象,所有已加载的业务代码每执行一行、命中一个分支、调用一个函数,都会实时在这个对象中更新对应的执行记录。 - 对接现有Selenium测试链路收集埋点数据
不需要改造你现有的Selenium自动化测试逻辑,只需要在每个Selenium用例执行完成、关闭浏览器页面之前,通过Selenium的JS执行能力读取当前页面的window.__coverage__对象,将内容序列化为json字符串,保存为本地的临时coverage文件即可。
你有nyc使用经验的话,完全可以复用nyc的工具能力:等所有Selenium用例执行完成,直接用nyc merge ./临时coverage文件目录 ./final-coverage.json命令,把所有分散的埋点数据合并成一份完整的覆盖率统计数据集,不需要自己开发合并逻辑。 - 生成标准化的覆盖率报告
合并完成后,直接使用你熟悉的nyc命令生成报告即可,比如执行:nyc report --reporter=text --reporter=html --temp-dir=./
命令执行完成后,即可在指定输出目录生成和你之前在Node/Express项目中体验完全一致的覆盖率报告,清晰展示各个模块的行覆盖率、分支覆盖率、函数覆盖率、语句覆盖率情况。因为配置了sourceMap映射,报告中的代码位置会直接关联到你编写的原始Angular TS源码,不需要对照编译后的打包代码手动定位。
常见踩坑提示
- 不要在生产构建场景下直接开启无配置的覆盖率统计:如果是用于生产环境对外提供服务的构建包,注入覆盖率埋点会额外增加包体积,建议仅在内部测试的本地/预发环境开启该能力。
- 收集覆盖率时要覆盖所有懒加载模块:Angular应用的懒加载路由对应的代码块只有被触发访问时才会被浏览器加载,如果Selenium测试没有访问对应路由,这部分模块的代码执行记录就不会被收集,会导致最终统计的覆盖率结果偏低。
- 保证测试过程中页面不被强制刷新、不发生跨域跳转:一旦页面发生整页重载,
window.__coverage__对象就会被重置,之前收集的执行记录就会丢失,在Selenium测试的流程设计上要注意在页面重载前先把当前的埋点数据读出来保存。
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

