test(windows): make coverage fixtures portable
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Agent Note: 让受支持平台的测试聚焦语义
|
||||
|
||||
Status: implemented
|
||||
|
||||
[English](2026-07-22-cross-platform-test-fixtures.md) | 中文
|
||||
|
||||
## 问题
|
||||
|
||||
单元测试与覆盖率测试套件会在 Windows、macOS 和 Linux 上运行,但平台无关行为可能被平台特有的 fixture(测试前置数据)掩盖。字面 POSIX 路径在 Windows 上会变成相对于驱动器的路径;带主机名的 `file:` URI 在 Windows 上可能是有效的 UNC 路径;在 Node 中,编号为 `0` 的文件描述符也不是子进程管道型 stdin 的唯一持有者。FIFO、可执行模式位和目录搜索权限位等仅存在于 POSIX 的文件系统状态,在 Windows 上没有可直接构造的 fixture。
|
||||
|
||||
把 fixture 语法当成产品行为,要么会误报回归,要么会促使生产代码引入抹去原生路径语义的归一化。
|
||||
|
||||
## 决策
|
||||
|
||||
测试平台无关行为时,使用宿主的 `node:path` 和 `node:url` API 构造绝对路径与 `file:` URI,再根据契约要求断言原生绝对输出或稳定的工作区相对输出。无效 URI fixture 使用一种在所有受支持平台上都会被 `fileURLToPath()` 拒绝的编码形式。
|
||||
|
||||
需要使父进程写端失败的子进程 fixture 会同时关闭 CRT 文件描述符和持有子进程 stdin 的 libuv 句柄。这种方式在以 POSIX 文件描述符为后端的进程和以 Windows 管道为后端的进程上固定了连接失败契约,同时让子进程存活足够长的时间,以区分管道故障与进程退出。
|
||||
|
||||
对于真正仅存在于 POSIX 的原语,测试只在该用例上排除 Windows。相邻的跨平台用例仍会固定拒绝非普通文件、不可用命令和无法访问的工作目录的行为。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
**将所有路径和 URI 归一化为 POSIX 字符串。**这会使断言保持一致,但也会改变正确的 Windows 行为:外部路径是原生绝对路径,UNC 文件 URI 有效,而且已配置的主目录会按照宿主路径规则解析。
|
||||
|
||||
**在 Windows 上通过兼容性 shell 运行 POSIX fixture。**这种兼容环境测试的文件系统与进程语义不同于产品实际使用的原生 Node 运行时。
|
||||
|
||||
**在 Windows 上跳过整个测试文件或包。**过宽的排除会隐藏受支持的行为。只排除无法在 Windows 上构造相应状态的单项 fixture;相关契约仍保持覆盖。
|
||||
|
||||
## 后果
|
||||
|
||||
可移植 fixture 略显冗长,因为预期路径需要从共享的原生常量派生。仅适用于特定平台的排除项必须配有相邻的跨平台断言,以继续覆盖相应的产品行为。管道故障 fixture 依赖 Node 测试运行时的句柄形态,但这种依赖仅存在于脚本化的子进程内;因此,这类 fixture 验证的是真实的父进程侧流行为,而不是对它进行 mock。
|
||||
Reference in New Issue
Block a user