@adlc/hollow-test

中文文档
1.12.0发布于 2026/10/10MITES Module构建来源已验证近 30 天下载 8199

Diff-scoped突变门-诚实覆盖检查,只变换行(P3/C4).

中文使用文档
文档目录16 节
  1. 使用量
  2. 旗帜
  3. 退出代码
  4. --max 对 diff 来说太小: 已饿死的文件无法关闭
  5. --target 编号 : --rails : P3 铁路授权/特征测试
  6. 实例
  7. 安全保障
  8. 哪些变异( 哪些被跳过)
  9. 仅报告评论的更改为未涵盖
  10. 无效的变种人
  11. 变异运算符(来自 @adlc/core (中文(简体) )
  12. JSON 输出计划
  13. 与兄弟姐妹工具的关系
  14. 核心差距
  15. 执行说明
  16. NODE TEST CONTEXT 剥离

空心测试

ADLC相:P3出入口(C4-diff-scoped surfion) 出入口:

Diff-scoped突变门-诚实封面检查. 只变换行 在您的 diff 中更改了, 运行您的测试套件对每个变种人, 如果失败 任何变异都会活下来 幸存的变种人证明了空洞的覆盖: 但他们的行为不受任何断言的约束.

Diff - scroping 将运行时间控制在秒到分之间,而不是时间 杀死全码基突变测试.

使用量

hollow-test --test-cmd "node --test test/" [options]

旗帜

旗帜默认说明
--test-cmd <cmd>(必须)壳牌命令运行测试套房. 失败时必须离开非零.
--base <ref>HEADGit Base ref for the diff (例如:. HEAD~1, (中文(简体) ), main一个SHA.
--max <n>20所有文件的最大总变种人 。 预算是分散的循环循环.
--timeout-ms <n>120000一次性测试命令超时, 以毫秒计 .
--target <file>(无)直接改变此文件, 独立于 diff( repeatable) 。 绕过测试/ spec路径排除,并变换整个文件,而不仅仅是diff-changed行.
--rails <ticket-file>(无)一张JSON票文件的路径;其已申报 rails 缩写比对 git ls-files 并添加为突变目标(可重复).
--json(关闭)机器可读JSON输出(用于管弦乐手).
--help(关闭)显示使用和退出 0.

退出代码

代码含义
0出道口——所有变种人被杀死.
1操作错误 — 肮脏的工作树, 不是 git repo, 糟糕的论点, 无可突变 (diff中没有符合条件的源文件,也没有 --target 也没有 --rails ),或a 所选文件没有收到突变预算 (见下文).
2门故障——一名或多名变种人幸存(霍洛覆盖).

--max 对 diff 来说太小: 已饿死的文件无法关闭

--max 将变种预算圆旋边分布到每个选定的文件,并小 --max 对宽的diff可以留下一个或多个diff衍生文件 零配额 —— 说 从未变异过 那文件的更改代码 之后没有验证,所以 hollow-test 拒绝 以报告通行证:它退出 1 并列出每个被饿死的文件 而不是沉默 传递其他文件 得到的预算。 提升 --max 覆盖所选文件 (每个文件至少更改一个),或缩小diff:

$ hollow-test --test-cmd "node --test test/*.test.mjs" --base HEAD~1 --max 1
error: 2 selected file(s) received no mutation budget and were NOT prosecuted: src/b.mjs, src/c.mjs — raise --max to cover them.

这不适用于收到预算但没有可变行的文件(a) ——这个案件仍然只是警告,因为文件是真实的 而不是因为预算不足而跳过.

--target 编号 : --rails: P3 铁路授权/特征测试

添加一个 diff 只测试文件 ——正是P3铁路的造型,或者 一种特征测试票,将现有的、不变的(冷冻-铁路)行为钉住——有 没有 filterTargetFiles()'diff 范围可变. 而不是默默报告 空闲 0编号 :0编号 :0 通行证, hollow-test 输出 1 在这种情况下,除非给出明确的目标:

# Diff is test-only (new rails for src/foo.mjs, which itself didn't change) — mutate
# src/foo.mjs directly so the new rails are actually prosecuted:
hollow-test --test-cmd "node --test test/foo-rails.test.mjs" --base main \
  --target src/foo.mjs

# Same, but read the target from a ticket's declared "rails" (single-ticket object or a
# full tickets.json — rails merged across all tickets in the file):
hollow-test --test-cmd "node --test test/foo-rails.test.mjs" --base main \
  --rails .adlc/tickets.json

实例

# Check the last commit
hollow-test --test-cmd "node --test test/" --base HEAD~1

# Check staged changes vs main
hollow-test --test-cmd "npm test" --base main --max 30

# Machine-readable output for CI
hollow-test --test-cmd "node --test test/*.test.mjs" --json

安全保障

  1. 肮脏的树木检查: 如果 git status --porcelain 不为空. 这样可以防止不小心离开损坏的文件, 如果进程是 中断 。 先提交或保存您的更改 .

  2. 文件恢复: 每个变异文件通过 a 恢复 try/finally 块 - 即使测试命令崩溃或进程通过 签字。 SIGINT 处理器在退出前进行紧急恢复.

  3. 顺序处决: 变种人一次应用并测试一次 (绝不平行)避免同时写到同一个文件.

  4. 绿色基线:在变异前需要绿色基线,所以失败的套房不能伪装成杀死每一个变异者. 如果基线套件失败,空心测试会在出站前将测试命令所捕获的stdout和stderr释放出stderr,确保失败原因和失败测试是可诊断的.

  5. 暂停结束所有开始的套房:每次审判都经过一个 小型看管儿童(lib/watchdog.mjs保持套房在你自己的 过程组和会话,在超时起火时,冻结被害者(SIGSTOP,向外取根,重新收起) 直到稳定,所以在杀戮期间叉子不能因为被再生而滑出) 然后用SIGKILLLL他们。 受害者是贝壳的活生生的后代 加上,在 Linux, 环境仍然带有外壳标记的每个进程 开始于(链条,所以一个有巢穴的空心测试 延伸它而不是) 把它的树树藏在外边,它抓住一个帮手 更早的审判中双叉或脱去. 任何结束于 外壳本身在空心测试的stderr上随其发生而命名(并折叠成 所以,一个守护进程 套件的脱落不是 无声地消失 父链接来自 /proc 在没有分叉的Linux上, 因此,这个在它存在的内存- 渴望的主机上工作; 其他平台使用 时间框 ps 只有活树, 监督者也会投票给父母: 如果空洞试验本身被彻底地杀死kill -9来电暂停,它 结束了套房和出入口 而不是被困在这里。 同样的扫荡 在 Ctrl- C 上运行( 弹壳启动) & 包含 SIGINT 的作业被忽略, 因此是一个助手 开始于 server & npm test 以及任何时间 壳单出,所以坠毁 node --test 不能拖着工人 超过超时(在路径上,贝壳已经收割,所以) 只有标记扫描仍然可以命名它留下的东西,在Linux上). 还有什么 逃出:一个在解开后清洗自身环境的过程,以及一个 无法读取的平台上的解开助手 /proc在这一切之前, node --test它的档案工作者和任何 套房产出的生命 作为孤儿的每一个定时变种人 仍然执行变种密码 一堆 他们把一个主机 下来(2026-10-08): RAM和互换 满了,没有杀死,SSH 登录从未获得外壳). Windows运行未被封存的命令 .

  6. 每个节点都有一个V8高盖: 测试命令开始的每个节点都得到 --max-old-space-size 通过 NODE_OPTIONS (默认2048 MiB,由 使得JS-heap生长不受限制 死后用"堆积出内存"而不是运行到超时. 这是一个 每个进程绑在一个隔离器的旧空间上,而不是一个主机绑定 : node --test 并行运行文件, 缓冲、 缓冲缓冲和本地内存在外 它(2026-10-08出逃是一股无尽的"缓冲"). 锁定主机 有组( c)systemd-run --scope -p MemoryMax=…; 依赖担保 5 到 结束一个逃跑. HOLLOW_TEST_MAX_OLD_SPACE_MB=<n> 更改上限; 0 禁用 它; 当变量未被设定时, a --max-old-space-size (或 --max_old_space_size你已经放进去了 NODE_OPTIONS 保存; 设置时,它取代任何被继承的旗帜。 基线运行使用相同的设置,所以一个真正需要的套房 更响亮的失败在那里,不是沉默的中门, 和标本它打印的名字 盖和变量。 默认值低于节点本身的大型默认值 主机; 需要更多设置变量的套件 .

哪些变异( 哪些被跳过)

突变仅适用于平版 JavaScript : .mjs, (中文(简体) ), .cjs, (中文(简体) ), .js。这是一个 允许列表. TypeScript和JSX (中文(简体) ).ts, (中文(简体) ), .mts, (中文(简体) ), .cts, (中文(简体) ), .tsx, (中文(简体) ), .jsx, (中文(简体) ), Python, CSS 和其他一切都排除在外, 因为操作员是 基于文本且无法从类型参数或JSX中分辨比较 分隔器 - Promise<unknown> 变成无效 Promise>=unknown>,则a 解析失败目前被评为 a 被杀死 变种人. 参见第293期.

路径时文件也会被跳过 部分 实值 test, (中文(简体) ), tests, (中文(简体) ), spec, (中文(简体) ), specs,或 __tests__,或何时 碱性名称 匹配一个 node --test 发现公约: test.js, (中文(简体) ), test-*, (中文(简体) ), test_*, (中文(简体) ), *-test.*, (中文(简体) ), *_test.*, (中文(简体) ), *.test.* (和 spec (见a/c.5/49/70,附件).

匹配是局部和基名故意的: 次弦测试会 排除生产途径,例如: packages/hollow-test/lib/targets.mjs 或者说 lib/attest.mjs。 。 。 .

两个逃出舱门, 因为没有公约解决每一个案件:

  • --test-glob <glob> - 将其他路径作为测试.
  • --source-glob <glob> - 将路径当作生产来源,即使它们的名称 符合试验公约。 需要产品名称,如 hollow-test.mjs 财务报告和审定财务报表 spec-lint.mjs,仅通过命名就无法与测试区分. 出于同样的原因, 连字符 表单( 表格)foo-test.js, (中文(简体) ), spec-foo.js已经 没有 作为测试处理——测试之间的连字符模糊不清 公约和产品名称,以及 hollow-test.mjs 财务报告和审定财务报表 spec-lint.mjs 为: 生产文件。 如果你用那条公约, 保持测试在一个 test/ 目录 或命名他们 *.test.*。 。 。 . --target编号 :--rails 文件绕过 测试路径 排除——呼叫者是 故意给突变目标取名,而铁路通常是测试文件.

没错 没有 绕过语言允许列表。 操作员为JS/TS形,以及 使另一种语言在战术上无效的变异者进行测试 命令退出非零,该数值为 被杀死 假的通行证 所以说:

  • --target <path> 在不支持的语言中 拒绝 (出处1). 这个 呼叫者给一个文件取了名字;默默地放弃它将是它自己的无声通道.
  • --rails <ticket> 扩展合法匹配非源( e)schemas/**, (中文(简体) ), JSON,固定装置)。 这些被过滤出来 报告运行失败 只有在没有变异物存在的情况下.

在 diff 衍生的合格文件中, 仅 diff 中更改的行是 目标; --target编号 :--rails 文件全部变异。 线条 空白、评论、进口、, export {,或 console.* 电话被跳过.

仅报告评论的更改为未涵盖

更改后的文件, 其程序没有被更改—— 只有注释或空白 添加、重写或去除行——没有可变行为。 它没有失败;它 在 stdout 上列出未覆盖,当它是唯一的更改时,运行出口 0 与 comment-only diff — no changed behaviour to mutate与 --json 页:1 同一文件出现在 "skipped": { "commentOnly": [...] },在早期退出时 和正常报告一样.

双侧的diff 被判断,所以这些是 没有 仅批注并留下 变异目标(在无可变残骸时关闭):

  • 已删除并被注释或空白行所取代的代码行;
  • 以添加方式包裹的活代码 /* . */· ;
  • 删除 */ 将后面的代码变为注释文本;
  • (单位:千美元) // ... 在多行模板文字内行,这是字符串数据.

任何疑义 — 一个无法读取的文件, 一个无法读取的旧面 --base页:1 扫描丢失其位置——保持文件目标.

无效的变种人

生成代码节点无法解析的突变是 丢弃没有得分. 基于线路的运营商定期生产这些产品—— null-return 重写 a 多线 return { 改为 return null; 并绑起对象的文字 剩余行.

这很重要 因为一个杀手是从一个非零出口 和一个文件推断出来的 不分析同时退出非零。 计算这样的变种人 被杀死 伪造 覆盖; 计为 幸存下来 将从未有过的代码归咎于测试 无效。 报告本身 invalid 在桌子和JSON两个都装入桶子.

若为 每个 运行中的变异是无效的, 空洞的测试出口 1个 (业务 而不是通过:没有行使任何断言,因此运行证明 没什么.

审定用途 node --check,所以不添加解析器依赖度和真实 文件扩展名和软件包类型都得到了遵守。 语法检查和测试都是 三态 —— 说 valid, (中文(简体) ), invalid,或 unknown."可能不会 确定“ 永远不会崩溃为“ 有效 ” : 如果检查器被杀死, 时间已过期, 或 不能产卵,运行失败 操作而不是猜测。 测试命令本身也是如此:产卵故障(EAGAIN, ENOMEM)不是超时,超时是唯一算作杀活的未完成. 杀死一定意味着测试失败了 假设 有效性将运行测试命令以对抗无法解析的源,其非零 退出后被评为杀出——这一关上的道路.

完全无效的警卫被应用 每个文件不只是全球范围 全球检查 任何其它文件一旦失效 就会被明确允许 名称 --target 运行报告成功时完全没有测试.

变异运算符(来自 @adlc/core(中文(简体) )

运算符示例
invert-comparison=== → !==, (中文(简体) ), <= → >
bool-fliptrue → false
null-returnreturn expr → return null
off-by-one字义 n → n+1
logic-swap&& → ||

off-by-one 不改变调制常数. +1 期限 毫秒或以字节表示的大小是一个 等同变异者 - 任何测试都无法观察 60000 -> 60001 在子进程超时时数上 ms- 因此生成需要测试 这不可能存在(# 359)。 规则读取常数 名称,拆分为 部分,以及 snake_case编号 :camelCase 拼写相同 :

名称变异?为什么
GIT_TIMEOUT_MS, (中文(简体) ), maxBufferBytes, (中文(简体) ), TTL_MS没有次秒/ 字节 单位 - 不可观察的规模
timeout, (中文(简体) ), ttl, (中文(简体) ), maxBuffer, (中文(简体) ), highWaterMark没有已知调音符 语句
MAX_RETRIES, (中文(简体) ), retryLimit, (中文(简体) ), chunkSize, (中文(简体) ), timeoutRetries对跟踪 计数 字词——一个可计数的边界,不管名字上写了什么
RETENTION_DAYS, (中文(简体) ), GRACE_HOURS对粗糙的时间单位 实值 在注入的时钟下可观察到
{ ttl: 0 }, (中文(简体) ), { timeout: -1 }对0/负是离散的哨兵,而不是星等

后面的数字总是胜过名字中的调音短语,所以 扩大短语列表,永远不能默默地删除对一个伯爵的起诉. 命名 单位是获得面具的人 MAX_BUFFER_SIZE_BYTES 被蒙上阴影 MAX_BUFFER_SIZE 没有(# 372). | negate-guard-subclause | Array.isArray(x) ↔ !Array.isArray(x)· ; if (value) → if (!value); 松开 v == null ↔ v != null | | array-literal-shrink | ['id', 'title', 'scope'] → ['id', 'title'] | | ternary-swap | cond ? a : b → cond ? b : a |

JSON 输出计划

{
  "tool": "hollow-test",
  "summary": {
    "total": 5,
    "killed": 4,
    "survived": 1
  },
  "mutants": [
    {
      "file": "src/calc.mjs",
      "line": 7,
      "operator": "null-return",
      "status": "survived",
      "timedOut": false,
      "original": "  return a + b;",
      "mutated": "  return null;"
    }
  ],
  "skipped": { "commentOnly": ["src/notes.mjs"] }
}

skipped 仅当更改的文件被保留为仅作为注释时才会存在.

与兄弟姐妹工具的关系

  • 护栏(C5): 执行在构建过程中不修改测试文件 (它们是测量仪器) 空心测试验证这些测试 实际限制行为.
  • 审查-校准(C8): 使用同样的 mutate 植入错误的操作员 并量检校者的记忆。 空心测试和审查-校准共享核心 变相机械.
  • 闪光探测器(C6):空心测试为P3门;花纹探测器手表 p4构建会议。 它们服务于补充阶段.

核心差距

无。 所有需要的功能(gitDiff, (中文(简体) ), isDirty, (中文(简体) ), isGitRepo, (中文(简体) ), git, (中文(简体) ), globMatch, (中文(简体) ), mutate.generateMutants, (中文(简体) ), mutate.applyMutant, (中文(简体) ), mutate.changedLinesFromDiff, (中文(简体) ), parseArgs, (中文(简体) ), pass, (中文(简体) ), gateFail, (中文(简体) ), opError, (中文(简体) ), printJson) 可在 @adlc/core。 。 。 .

执行说明

NODE TEST CONTEXT 剥离

节点.js v22 sets NODE_TEST_CONTEXT 在儿童过程环境中 运行在下 node --test。如果一个程序继承了该变量和 本身称谓 node --test,它默默地跳过所有测试文件(exits 0). 空心试验条 NODE_TEST_CONTEXT 儿童环境的影响 运行每个变种人的测试命令。 这确保了突变审判工作 即使空心测试本身在测试带内运行 也是正确的.

版本与发布记录

@adlc/hollow-test 共发布 18 个版本,首次发布于 2026/06/14;过去 12 个月发布了 18 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.12.0latest2026/10/1027 天前
1.11.12026/09/091 个月前
1.11.02026/08/252 个月前
1.10.02026/08/112 个月前
1.9.02026/08/092 个月前
1.8.02026/08/082 个月前

关于 @adlc/hollow-test 的常见问题

@adlc/hollow-test 是什么?

Diff-scoped突变门-诚实覆盖检查,只变换行(P3/C4).

如何安装 @adlc/hollow-test?

在项目目录运行 npm install @adlc/hollow-test,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 hollow-test,可以用 npx hollow-test 直接运行。

@adlc/hollow-test 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/adlc__hollow-test 是否存在。

@adlc/hollow-test 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@adlc/hollow-test 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@adlc/hollow-test 可以商用吗?

@adlc/hollow-test 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@adlc/hollow-test 的下载量有多少?

根据 npm 官方下载统计,@adlc/hollow-test 在 2026/10/05 – 2026/11/03 这 30 天内被下载 8,199 次,日均约 273 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@adlc/hollow-test 还在维护吗?

最新版本 1.12.0 发布于 2026/10/10(27 天前);至今共发布 18 个版本,其中过去 12 个月发布了 18 个;首次发布于 2026/06/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。