Skip to content

test: 接入 Stryker 变异测试与增量 CI - #216

Merged
yourtion merged 6 commits into
mainfrom
feat/stryker-mutation-testing
Oct 20, 2026
Merged

yourtion merged 6 commits into
mainfrom
feat/stryker-mutation-testing

Conversation

@yourtion

@yourtion yourtion commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

本 PR 为现有 Vitest 测试引入 StrykerJS,补充测试并修复变异测试暴露的文档生成、TestAgent 和工具函数缺陷,增加可复用主分支基线的变异测试 CI。

  • Stryker 仅变异 src/lib/**/*.ts,默认增量;mutation:full 可强制全量重建,保留 mutation:incremental 命令。
  • 新增 Mutation Testing 工作流(Node.js 24 / pnpm 9):PR 只读取主分支兼容基线,主分支成功后保存;缓存缺失自动全量。依赖、配置、测试辅助文件和 adapter 源码变化会使缓存失效。
  • 支持手动 full 重建;PR 新提交可取消旧运行,主分支运行不主动取消。失败时仍上传可用报告,保留 14 天;不新增最低分门禁。
  • 源码模式(ISLIB)下将 adapter 内部的精确 erest 包名导入映射到源码入口,避免洁净 CI 因缺少 dist 而失败,也让 adapter 使用被 Stryker 变异的源码。未设 ISLIB 的发布产物测试仍通过包 exports 解析。
  • 补充 README 使用说明,并修复原分支一处导致格式检查失败的换行。

验证:

  • 删除 dist 后复现首次 CI 的 13 个测试套件入口解析失败;修复后在无 dist 环境中 599 个源码测试全部通过。
  • 同一无 dist 环境下,对 src/lib/adapters/utils.ts 完整执行 52 个变异:50 killed、2 survived、0 timeout、0 error,分数 96.15%;Stryker 原始测试 599 个通过。
  • pnpm 9 frozen-lockfile 安装、pnpm run check、覆盖率门槛通过;重新构建后的 604 个发布产物测试和 13 个示例测试通过。
  • actionlint 1.7.11 校验新工作流通过。
  • 新增 5 个回归用例覆盖 Zod 3/4 对象缺失 shape、流读取 Error/非 Error 异常及损坏 JSON 响应;604 个源码测试通过,agent.ts 和 Markdown schema.ts 行覆盖率均为 100%。本地与 main 对比的 133 行新增语句全部覆盖,不降低 Codecov patch 门槛。
  • 此前使用独立临时基线完成单文件增量验证:首次生成 32 个变异结果,第二次复用 32/32,强制运行复用 0/32。

完整 PR CI 已在提交 66ae3d4 通过:Mutation Testing 运行记录。29 个源码文件共 3,070 个变异,分数 90.10%(2,766 killed、292 survived、12 no coverage、0 timeout、0 error),耗时 28 分 36 秒;HTML/JSON/增量报告已上传为 mutation-reports-39365616418-1 artifact。Codecov patch 100%、项目覆盖率 99.86%,Node 20/22/24、CodeQL 和 Snyk 均成功。当前仍有存活变异,不新增评分门禁;合并后首次成功的 main CI 才建立共享基线。

- 新增 stryker.config.json:mutate src/lib/**,perTest 覆盖分析,html + clear-text 报告
- package.json 新增 mutation / mutation:incremental 脚本(ISLIB=1 直跑源码)
- pnpm-workspace.yaml:allowBuilds esbuild 迁移修正(pnpm v11 不再读 package.json 内 pnpm 字段)
- .gitignore 排除 .stryker-tmp/ 与 reports/
- README 新增「开发」章节说明本地测试与变异测试命令

全量首跑:3007 mutants / 12m31s,总分 44.93%(killed 1351 / survived 1416 / no-cov 240)
按模块为存活 mutant 补充内容级精确断言,全部融入现有测试文件:
- test-docs-zod.ts(25→88 例):markdown 生成器全模块 + extend/docs 协调器
- test-docs-plugins.ts(9→58 例):swagger/postman 内容断言 + axios SDK 全文比对
- test-error-formatter.ts(4→21 例):默认错误表精确值 + ErrorManager + debug 命名空间
- test-zod-native.ts(7→43 例):compileValidate 全分支 + zodTypeMap 全别名
- test-zod-meta.ts(18→40 例):Zod 3/4 双轨兼容矩阵
- test-test.ts(42→90 例):TestAgent 行为 + IAPITest 引擎 + test-server 归一化
- test-lib.ts(47→85 例):门面选项归一化 + utils/adapters/manager
- test-api.ts(14→22 例):构造校验 + define 归一化 + registerTyped
- test-hooks.ts(4→7 例):hasHooks 真值表
- stryker.config.json 增加 json reporter(增量模式与离线分析)

全量 588/588 通过。重跑 Stryker:killed 1351→2698、survived 1416→295、
no-cov 240→14,总分 89.72%(7m04s,比首跑更快)。
文档生成器:
- generate_axios 路径参数模板 \$ 转义导致 SDK URL 参数永不生效 → 生成 ${id} 正常插值
- generate_swagger 路径占位符 replace 缺 /g,多参数路径只转换第一个
- generate_swagger POST body 字段级 required 丢失(死代码)→ 聚合进 schema.required
- generate_markdown/schema zod4 下数组元素恒 unknown[]、枚举取值恒空 → 走 zod-meta 双轨
- generate_markdown/schema falsy 默认值(0/false)渲染为空 → ?? 如实展示
- generate_markdown/apis 无 input 示例渲染字面量 undefined 文本
- generate_markdown/types 对象数组 sort() no-op 清理

TestAgent:
- 多 Set-Cookie 响应头相互覆盖(forEach 后值盖前值)→ getSetCookie() 合并
- attach 流被 undici FormData 隐式 String() 成 [object Object] → 请求时读尽为 Blob
- GET/DELETE + attach 抛 fetch 底层错误 → 提前断言并给出中文提示

工具函数:
- getCallerSourceLine ESM 无括号栈帧(file:// URL)恒返回空 → 双风格兼容
- jsonStringify replacer 死代码简化
- ErrorManager.modify 换 code 后旧 code 释放 + 新 code 冲突校验

约定 6 收敛:generate_axios/swagger/postman 的 _def 直读全部迁移到 zod-meta
统一访问器(新增 resolveZodShape/getZodElement/getZodEnumValues/getZodOptions/
getZodDefaultValue/getZodLazyGetter 导出)。

版本 3.2.2 → 3.2.3,MIGRATION.md 登记。
验证:全量 599/599(含 build + dist 模式 + examples 13/13)、tsc 通过、
Stryker 重跑总分 89.64%(utils.ts 60% → 74%)。
@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.86%. Comparing base (ffe0ffa) to head (66ae3d4).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #216      +/-   ##
==========================================
+ Coverage   92.54%   99.86%   +7.31%     
==========================================
  Files          28       28              
  Lines        2939     2962      +23     
  Branches      770      913     +143     
==========================================
+ Hits         2720     2958     +238     
+ Misses        217        4     -213     
+ Partials        2        0       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@yourtion
yourtion merged commit 6e83af3 into main Oct 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant