Novu API E2E 测试实战:用 mocha 全量与定向运行 novu-v2 端到端测试套件 Novu API E2E 测试实战用 mocha 全量与定向运行 novu-v2 端到端测试套件【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novunovu-v2 是 Novu开源通信基础设施新一代 API 版本线其端到端测试散布在apps/api的src/与e2e/enterprise/目录中并以#novu-v2标签统一标记。本文以仓库中的 Agent 技能文档 run-api-e2e-tests/SKILL.md 为骨架结合 apps/api/package.json、run-novu-v2-e2e-shard.cjs 与 e2e/setup.ts 的真实实现完整讲解「一条命令跑全量」「精准定位并只跑单个用例」「理解每个 mocha 参数与环境变量」三个层次的用法。读完后你可以在本地、CI 分片甚至 CE-only fork 场景下自主运行、排查并汇报 Novu API 的 E2E 测试结果。这套 E2E 测试在仓库中的位置与定位运行入口位于 API 服务目录apps/api。E2E 测试文件使用两个命名约定通用Community/核心套件*.e2e.ts企业版Enterprise专属套件*.e2e-ee.ts同时也保留单独的e2e/enterprise/目录当前检出中可见 conversations 与 inbound-webhook 两个套件。不是所有 E2E 文件都会被 novu-v2 套件纳入。真正的筛选标准是文件内容中是否包含#novu-v2标签——它通常出现在describe(...)描述字符串中例如trigger-event-preferences.e2e.ts位于src/bridge-trigger.e2e.ts 中的Self-Hosted Bridge Trigger #novu-v2process-inbound-webhook.e2e.ts 中的Process Inbound Webhook E2E #novu-v2。运行这些测试会真实启动应用e2e/setup.ts会在before()阶段丢弃 MongoDB 测试库、清理 ClickHouse、执行bootstrap()拉起 NestJS 应用再通过testServer.create()与健康检查等待服务就绪after()阶段再做 teardown 与清理。一键运行全量pnpm test:e2e:novu-v2在apps/api目录下运行pnpm test:e2e:novu-v2该命令会跑遍 novu-v2 模式下的全部E2E 测试既包括普通套件也包括企业版套件。注意你并不需要自己拼一条超长命令——pnpm script 已经封装好了。这个 pnpm script 底层做了什么查看 apps/api/package.jsontest:e2e:novu-v2: cross-env TS_NODE_PROJECTtsconfig.spec.json NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 --no-experimental-strip-types node scripts/run-novu-v2-e2e-shard.cjs它并没有直接调用 mocha而是转交给了 run-novu-v2-e2e-shard.cjs 这个分片调度器该脚本按如下逻辑工作收集候选文件非 CE-only 模式下扫描src/与e2e/enterprise/两个根递归匹配\.e2e(-ee)?\.ts$参见collectTestFileRoots/getTestFilePattern按标签过滤跳过不包含#novu-v2的文件按用例数量加权用正则\bit(?:\.only)?\s*\(/g数出每个文件里it(/it.only(的个数作为 weight贪心分片将文件逐个放入当前最轻weight 最小、文件最少的分片使各分片负载均衡buildShards/pickLightestShard构造 mocha 参数并串行执行runMocha固定带上--timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts。分片与 Reporter 的可调入口调度器对外暴露了更细的控制项这些对 CI 或超长套件非常实用分片参数命令行--shard2/4或环境变量NOVU_V2_SHARD_INDEX、NOVU_V2_TOTAL_SHARDS默认均为1/1仅打印当前分片将运行的文件而不执行附加--listReporter默认本地为spec、CI 下为dot可用NOVU_V2_MOCHA_REPORTER覆盖在 CI 环境还会自动追加--bail并默认注入LOG_LEVELfatal、NEW_RELIC_ENABLEDfalse、NODE_NO_WARNINGS1applyDefaultEnv。只测社区版test:e2e:novu-v2-ce如果你的改动面向社区版CE例如不开企业版功能的 fork PR应使用 package.json 中定义的pnpm test:e2e:novu-v2-ce它设置CI_EE_TESTfalse NOVU_V2_CE_ONLYtrue调度器此时只扫描src/下的\.e2e\.ts$文件并从白名单CE_EXCLUDED_FILES中排除混入了云端 EE 专属行为出站 SSRF 校验、Stripe 计费周期、RBAC 权限、翻译、novu-app MCP 等的用例文件例如src/app/auth/e2e/permissions.guard.e2e.ts、src/app/events/e2e/trigger-event-ssrf.e2e.ts。定向运行单个测试文件三步定位法当你想跑某个具体特性或模块的测试时按以下三步走找到测试文件在apps/api中用 glob 模式*.e2e.ts或*.e2e-ee.ts搜索提取文件名去掉扩展名——例如trigger-event-preferences.e2e.ts→trigger-event-preferences判断测试所在目录它是在src/下还是在e2e/enterprise/下按所在目录选择对应的完整 mocha 命令。重要定向运行不要使用pnpm test:e2e:novu-v2之类的 pnpm script而应直接使用完整 mocha 命令因为 pnpm script 会聚合所有匹配文件并做分片无法精准指向你关心的那一个文件。测试位于 src/ 目录时pnpm exec cross-env NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 mocha --timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts src/**/name-of-the-test.e2e{,-ee}.ts测试位于 e2e/enterprise/ 目录时pnpm exec cross-env NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 mocha --timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts e2e/enterprise/**/name-of-the-test.e2e.ts把name-of-the-test替换成真实文件名不带扩展名即可。注意带引号的文件 glob 由 shell 展开或交给 mocha 处理均可此处保留引号以匹配任意中间目录层级。逐项理解这些参数才能在排错时不迷路参数 / 环境变量含义与作用pnpm exec cross-env跨平台注入环境变量后执行后续命令避免 Windows / Linux 语法差异NODE_ENVtest让应用以测试环境启动start:test同级语义加载测试用配置CI_EE_TESTtrue声明当前运行包含企业版EE测试置为false时走 CE-only 分支CLERK_ENABLEDtrue启用基于 Clerk 的认证链路供涉及鉴权的 E2E 场景使用NODE_OPTIONS--max_old_space_size8192把 Node 老生代堆上限提到 8 GB避免大型套件 OOMmocha测试运行器对应apps/apidevDependencies 中的mocha ^10.2.0--timeout 30000单条用例 30 秒超时--retries 3失败的用例自动重试最多 3 次缓解偶发网络/时序抖动--grep #novu-v2只执行标题匹配#novu-v2的用例--require ./swc-register.js预加载 swc-register.js用 SWC 快速转译 TypeScript--exit全部用例跑完后强制退出进程避免残留句柄挂起--file e2e/setup.ts运行任何用例前先加载 e2e/setup.ts完成 DB 清库、应用 bootstrap 与健康检查等全局准备其中文件 glob 的{,-ee}是一个 bash 花括号展开技巧trigger-event-preferences.e2e{,-ee}.ts会同时展开为trigger-event-preferences.e2e.ts与trigger-event-preferences.e2e-ee.ts因此同一条命令即可命中某模块的普通版与企业版测试文件。两个可直接复制的实战示例示例一跑 trigger-event-preferences位于 src/该文件真实存在于 apps/api/src/app/events/e2e/trigger-event-preferences.e2e.ts覆盖触发事件时订阅偏好偏好中心对消息投递的过滤逻辑。定位命令# Found: apps/api/src/app/events/e2e/trigger-event-preferences.e2e.ts pnpm exec cross-env NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 mocha --timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts src/**/trigger-event-preferences.e2e{,-ee}.ts示例二跑企业版套件SKILL 文档给出的企业版范式是 billing计费场景——该能力依赖企业版EE包仅在CI_EE_TESTtrue时可用。在当前仓库检出中EE 专属的 billing 测试实际命名以-ee结尾并位于src/下的模块 e2e 目录例如 src/app/billing/e2e 系列而e2e/enterprise/目录中则存放 conversations、inbound-webhook 等独立套件。因此请以文件实际位置套用上面两条命令模板若测试在e2e/enterprise/下形如# Found: apps/api/e2e/enterprise/module/name.e2e.ts pnpm exec cross-env NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 mocha --timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts e2e/enterprise/**/name.e2e.ts例如要跑 apps/api/e2e/enterprise/conversations/conversations.e2e.ts会话 API标签Conversations API - /conversations #novu-v2即为pnpm exec cross-env NODE_ENVtest CI_EE_TESTtrue CLERK_ENABLEDtrue NODE_OPTIONS--max_old_space_size8192 mocha --timeout 30000 --retries 3 --grep #novu-v2 --require ./swc-register.js --exit --file e2e/setup.ts e2e/enterprise/**/conversations.e2e.ts跑测试前必须知道的全局环境与坑所有命令都必须在 apps/api 目录下执行无论是 pnpm script 还是 mocha 命令其相对路径./swc-register.js、e2e/setup.ts、src/**都以apps/api为基准。先在仓库根或其它目录运行都会因找不到模块而失败。setup.ts 对基础设施的硬依赖阅读 apps/api/e2e/setup.ts 可以看到运行前它要求MongoDB通过MONGO_URL连接DalService.connectbefore()中先dropDatabase()清库测试结束再清空并关闭连接ClickHouse默认http://localhost:8123默认库test_logs由CLICK_HOUSE_DATABASE覆盖会创建库并 TRUNCATE 其下所有表以保证 analytics 数据干净应用健康检查轮询http://localhost:${PORT}/v1/health-check最多 60 次、每次间隔 1 秒服务未就绪即失败。因此本地跑之前请确保对应服务可达否则会在全局before()阶段就报错。失败信息已经过加工先看日志再下结论afterEach钩子会对失败的断言做“翻译”后再输出ResponseValidationError、ValidationErrorDto、ZodError含union成员的递归展开都会有专门的格式化打印帮助区分“响应结构不符”与“业务断言失败”。遇到用例失败但原因不明时优先查看控制台中的这些结构化错误块。运行环境差异CI 与非 CI本地默认使用specreporterCI 使用dot并使用--bail首错即停同时setup.ts会屏蔽 CI 下Duplicate schema index之类的预期告警CE-only 模式下不要忘记企业版套件billing 等和部分混合文件会被跳过这些是预期行为而非测试丢失。结果汇报要明确运行完成后向协作者或记录的日志清晰说明跑的是全量还是哪个单文件、命令使用的分片/CE 开关、通过/失败/重试后的最终状态以及失败用例对应的错误摘要。这也是 SKILL.md 在Important Notes中特别强调的收尾动作。小结何时用哪条命令你的诉求命令提交前跑完整 novu-v2 回归pnpm test:e2e:novu-v2只回归社区版能力CE fork / PRpnpm test:e2e:novu-v2-ce只想跑某个模块的一个文件定位文件后套用上面的完整 mocha 命令CI 中水平拆分超长套件node scripts/run-novu-v2-e2e-shard.cjs --shardindex/total只想看某分片将运行哪些文件同脚本追加--list这套「全量 pnpm script 定向完整 mocha 命令」的双层运行方式既保证了 CI 上的完整覆盖与分片均衡又让本地开发时能够秒级定位单一模块是 Novu API 开发与测试排错中最高频的两把钥匙。【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考