源码测试与生成物地图
本文讨论 Codex 仓库中的测试资产,而不只有 tests/。一个行为可能由实现文件旁的单元测试、共享 harness 驱动的 集成测试、磁盘 fixture、insta snapshot、提交到仓库的 JSON/TypeScript schema,以及 Cargo 与 Bazel 两套构建入口共同约束。
这几类文件的维护方式不同:fixture 往往是人工设计的输入和预期状态;snapshot 是测试运行产生、 但必须人工审阅后接受的预期输出;schema 是 Rust 类型的派生产物,应由生成器整体覆盖;target/、 nextest archive 和 JUnit 报告则是一次构建的临时结果,不应提交。把它们都叫“测试文件”会失去最 重要的所有权信息。
本文先回答三个问题:测试逻辑在哪里、测试依赖什么资产、源类型变化后哪些生成物必须同步更新。
本文是一张测试选择地图,不用文件数量代替覆盖率。找到与改动边界匹配的 harness、fixture 或 generator 后,应停止横向清点,进入文末链接的行为专题和具体测试;文件数量只用于发现 资产分布与版本漂移。
1. 四类仓库资产
| 资产 | 权威来源 | 是否提交 | 正确修改方式 | 漂移如何暴露 |
|---|---|---|---|---|
| 测试代码 | Rust/TypeScript/Python 测试逻辑 | 是 | 人工编写 | 测试编译或断言失败 |
| fixture | 人工构造的输入、证书、JSON、预期目录 | 是 | 按场景编辑 | 行为测试失败 |
| snapshot | 测试表达式渲染出的预期文本/UI | 是 | 运行测试,审阅 .snap.new 后接受 | insta snapshot mismatch |
| schema / generated source | Rust 类型、proto 或导出注册表 | 是 | 运行指定生成命令 | fixture-match test 或 clean-worktree 检查失败 |
| 构建与测试产物 | 当前源码和工具链 | 否 | 由 Cargo/Bazel/CI 重建 | 不参与源码 diff |
这个分类的判断标准是“谁拥有语义”。例如 config.schema.json 虽然是 JSON 文件,却不应被当成手写 配置文档;它的语义来自 ConfigToml 与 schemars 约束。相反,apply-patch 场景中的 patch.txt 和 expected/ 是测试作者有意设计的规范案例,不能由当前实现反向生成,否则实现错误会 同时污染预期结果。
图中只有 snapshot 接受需要“测试结果 → 人工审阅 → 仓库预期”这条反向边。schema 不走这条路: 它应由源类型确定性生成,再通过 diff 审阅 API 变化。
2. 测试目录
当前 codex-rs 的主要测试布局可以压缩为下面这棵树:
codex-rs/
├── <crate>/src/
│ ├── *.rs # 实现旁的 #[cfg(test)] 单元测试
│ ├── *_tests.rs # 显式 path 引入的专用测试模块
│ └── snapshots/*.snap # 模块级 insta 预期输出
├── <crate>/tests/
│ ├── all.rs # 部分 crate 的集成测试聚合入口
│ ├── suite/*.rs # 按行为主题拆分的集成场景
│ ├── common/ # 该产品的共享 harness/test-support crate
│ └── fixtures/ # 磁盘输入与预期状态
├── core/tests/
│ ├── all.rs # Core 集成测试入口
│ ├── suite/*.rs # Turn、工具、审批、恢复、MCP 等端到端场景
│ └── common/ # core-test-support
├── app-server/tests/
│ ├── suite/*.rs # 面向公共 JSON-RPC 的集成场景
│ └── common/ # app-test-support
├── test-binary-support/ # 测试二进制 arg0/别名装配
├── utils/cargo-bin/ # Cargo 与 Bazel 的 binary/resource 定位桥
└── .config/nextest.toml # 并发、重试、慢测试和测试组策略在当前版本仓库中,可以统计到约 1138 个包含 #[cfg(test)] 或 mod tests 的 Rust 文件、300 个 tests/suite/*.rs 文件、97 个 fixture 文件和 759 个 .snap。数量只能说明验证面很大,不能代替 覆盖判断:TUI 一项就拥有 705 个 snapshot,而一个关键 Core 状态转换可能只需要一个结构化集成测试。
2.1 局部不变量
实现文件旁的测试适合纯函数、解析器、序列化和局部状态机。仓库当前规则要求新增测试模块优先放到 描述性 sibling 文件,再显式挂回实现模块:
源码位置:codex-rs/skills/src/parser.rs :: sibling test module
// 测试实现移到同目录文件,生产模块只保留显式挂载点。
#[cfg(test)]
#[path = "parser_tests.rs"]
mod tests;这样实现文件不会随着测试膨胀,也能从文件名直接定位测试主题。该规则不要求机械迁移历史内联测试。 断言优先比较完整对象,并使用 pretty_assertions::assert_eq 获得可读 diff;不建议为静态常量编写 没有行为价值的测试。
2.2 Agent进程边界
涉及 agent 逻辑时,仓库规则优先要求 Core 集成测试。core/tests/all.rs 本身只有聚合职责:
源码位置:codex-rs/core/tests/all.rs :: integration test root
// 聚合入口只公开公共错误类型并挂载 suite,不承载具体测试场景。
#![allow(clippy::expect_used)]
pub use codex_protocol::error;
mod suite;suite/mod.rs 再挂载按主题拆分的文件。这样审批、工具执行、context compaction、resume、MCP、 multi-agent 和网络策略等场景共享一个明确的测试入口,同时仍能按模块维护。
Core harness 的核心是 core-test-support:
test_codex创建隔离的CODEX_HOME、配置、认证、模型 server 与 session;responses用 wiremock 伪造 Responses API 和 SSE 事件流;ResponseMock保存收到的请求,允许按完整结构检查模型输入和 tool output;wait_for_event等待 Core 事件,而不是在测试中随意 sleep;- process、Hook、App、zsh fork 和 remote environment helper 复用真实边界。
下面的类图展示 Core 集成测试 harness 的主要 owner。builder 负责装配,harness 同时持有 mock server 和可操作的 TestCodex,ResponseMock 则独立保存收到的模型请求。
测试不是直接拼装一个私有 Session:TestCodex 仍通过 CodexThread 提交 Op 和等待 Event,mock 只 替换模型边界,因此能覆盖真实 Turn 与工具循环。
典型测试不是直接调用某个私有函数,而是给 mock server 安装一段模型事件,向 Codex 提交 Op::UserTurn,再同时检查外发 request 与回传 event:
源码位置:codex-rs/core/tests/common/responses.rs :: mount_sse_once usage
// 先安装确定的模型事件流,再通过真实 Core submission 驱动工具续轮。
let mock = responses::mount_sse_once(
&server,
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(
call_id,
"shell",
&serde_json::to_string(&args)?,
),
responses::ev_completed("resp-1"),
]),
)
.await;
codex.submit(Op::UserTurn { /* ... */ }).await?;
let request = mock.single_request();源码位置:codex-rs/core/tests/common/responses.rs 与 test_codex.rs。这类测试能同时覆盖模型协议、 Turn 驱动、工具路由和 history 回灌,代价是进程和异步资源更重。
App Server 使用独立的 app-test-support,测试从公共 JSON-RPC 方法进入,而不是绕过 server 直接 调用 Core。默认 builder 会准备可跨 app OS 与 exec OS 的环境;这对 connected app-server 与 exec-server 分居不同系统的场景尤其重要。
2.3 CLI二进制测试
assert_cmd::Command::cargo_bin 只理解 Cargo 的测试布局,Bazel 则把二进制和资源放在 runfiles。 Codex 用 codex-utils-cargo-bin 统一两种解析方式:
源码位置:codex-rs/utils/cargo-bin/src/lib.rs :: cargo_bin
// 优先读取构建系统注入的 binary 位置,只有缺失时才走 Cargo fallback。
use std::path::PathBuf;
pub fn cargo_bin(name: &str) -> Result<PathBuf, CargoBinError> {
let env_keys = cargo_bin_env_keys(name);
for key in &env_keys {
if let Some(value) = std::env::var_os(key) {
return resolve_bin_from_env(key, value);
}
}
}resolve_bin_from_env() 在 Bazel 环境通过 runfiles::rlocation 解析;没有环境变量时才进入 assert_cmd 的 Cargo fallback。真实实现位于 codex-rs/utils/cargo-bin/src/lib.rs::cargo_bin。 资源文件则使用 find_resource!:Cargo 下从 CARGO_MANIFEST_DIR 查找,Bazel 下从 BAZEL_PACKAGE 与 runfiles manifest 查找。测试若直接拼 target/debug/codex 或依赖当前工作目录,通常只能在一种构建系统中 通过。
test-binary-support 解决另一类问题:同一个测试二进制可以按 argv[0] 装配 Codex 的多调用别名, 并在测试线程启动前建立临时 CODEX_HOME。这让集成测试可以启动接近真实交付形态的 helper,而不用 为每条路径复制一个测试程序。
3. Fixture
fixture 的共同点是测试先读取它,再驱动实现;内容不应由本次被测实现自动推导。仓库中的典型类别 如下:
| 目录 | 内容 | 验证目标 |
|---|---|---|
apply-patch/tests/fixtures/scenarios/ | input/、patch.txt、expected/ | patch 后文件树必须精确匹配 |
tools/tests/fixtures/json_schema_policy/ | 各类外部工具 JSON Schema | schema 清洗、大小和安全 policy |
http-client/tests/fixtures/ | CA 与 intermediate PEM | TLS trust 与证书链 |
backend-client/tests/fixtures/ | task details JSON | 后端响应反序列化与 diff/error |
tui/tests/fixtures/oss-story.jsonl | rollout/event 故事流 | TUI replay 和渲染 |
exec/tests/fixtures/ | 模型最终输出文本 | apply-patch/exec 行为 |
apply-patch 的场景目录最接近可执行规范:测试先复制 input/ 到临时目录,应用 patch.txt,然后递归 快照最终文件树并与 expected/ 深比较。每个场景目录只表达一个操作或失败语义,因此同一套 fixture 可以被不同语言或平台的实现复用。
Fixture 失败时,第一反应不应是覆盖 expected/。应先判断变化来自规范调整、测试输入不完整,还是 实现回归。只有前两种情况才有理由修改 fixture。
4. Snapshot契约
insta snapshot 主要集中在 TUI,因为终端布局由多个 span、换行、宽度、状态和事件共同决定,逐字段 断言难以展示最终用户看到的画面。一个 .snap 文件同时记录源测试、表达式和规范化后的输出:
---
source: tui/src/chatwidget/tests/exec_flow.rs
expression: terminal.backend().vt100().screen().contents()
---
Would you like to run the following command?
...测试 mismatch 会留下 .snap.new。正确流程分三步:
- 运行相关测试,例如
just test -p codex-tui; - 用
cargo insta pending-snapshots或直接阅读.snap.new检查视觉变化; - 只在确认所有变化都符合预期后运行
cargo insta accept -p codex-tui。
cargo insta accept 不是修复命令,而是批准新的用户可见契约。仓库规则要求所有 UI 或文本输出变更 增加或更新 snapshot coverage,并把接受后的 snapshot 一起纳入评审。当前源码树没有遗留 .snap.new;新快照与已提交快照的差异需要结合测试语义判断。
Snapshot 测试还需要消除非语义噪声。路径、UUID、计时、终端宽度和颜色状态若不先规范化,会让同一 行为在不同机器上产生无意义 diff。TUI 测试中常见的 normalize_snapshot_paths、固定 terminal viewport 和 paused Tokio time 都服务于这一目的。
5. Schema 派生接口
Codex 把需要被编辑器、SDK、Hook runner 和外部客户端消费的协议产物提交到仓库。它们不是普通 fixture:生成器会先清空目标目录,避免类型删除后留下幽灵文件,再写入完整结果。
codex-rs/
├── core/
│ └── config.schema.json # ConfigToml 的 JSON Schema
├── app-server-protocol/schema/
│ ├── typescript/
│ │ ├── *.ts # ts-rs 类型
│ │ ├── v2/*.ts # v2 API 类型
│ │ └── index.ts # 导出索引
│ ├── json/
│ │ ├── *.json # 单类型 schema
│ │ └── codex_app_server_protocol*.json # bundle
│ └── precomputed/
│ ├── app-server-exports-stable.json.zst
│ └── app-server-exports-experimental.json.zst
└── hooks/schema/generated/
└── <event>.command.<input|output>.schema.json三组 schema 的共同闭环是“源类型 → 生成器 → 已提交产物 → drift test”。下面的时序图突出生成命令 只负责写产物,最终是否接受变化仍由测试和人工 diff 审阅决定。
如果 drift test 失败,首先审查 Rust 类型和 generator;直接修改 GeneratedFiles 会在下一次重生成时 被覆盖,也无法解释契约变化来源。
5.1 配置 schema
codex-config::schema::config_schema() 从 ConfigToml 生成 draft-07 schema,并补充仅靠 derive 无法表达 的组合约束;config_schema_json() 对 object key 排序,保证输出确定。仓库中的 fixture 由下面命令 更新:
just write-config-schemaconfig_schema_matches_fixture 会重新生成内存 schema,先做 canonical JSON 比较,再写入临时文件做 精确文本比较。失败信息直接给出 unified diff 和更新命令。因此修改 ConfigToml 但漏掉 config.schema.json,不会等到发布时才发现。
源码位置:codex-rs/core/src/config/schema_tests.rs :: config_schema_matches_fixture
#[test]
fn config_schema_matches_fixture() {
let fixture_path = codex_utils_cargo_bin::find_resource!("config.schema.json")
.expect("resolve config schema fixture path");
let fixture = std::fs::read_to_string(fixture_path)
.expect("read config schema fixture");
let fixture_value: serde_json::Value =
serde_json::from_str(&fixture).expect("parse config schema fixture");
let schema_json = config_schema_json().expect("serialize config schema");
let schema_value: serde_json::Value =
serde_json::from_slice(&schema_json).expect("decode schema json");
// 先比较 canonical value,排除对象 key 顺序等无语义差异。
let fixture_value = canonicalize(&fixture_value);
let schema_value = canonicalize(&schema_value);
if fixture_value != schema_value {
let expected = serde_json::to_string_pretty(&fixture_value)
.expect("serialize fixture json");
let actual = serde_json::to_string_pretty(&schema_value)
.expect("serialize schema json");
let diff = TextDiff::from_lines(&expected, &actual)
.unified_diff()
.header("fixture", "generated")
.to_string();
// 失败信息给出更新命令,但不会由测试自动覆盖受审阅的 fixture。
panic!(
"Current schema for `config.toml` doesn't match the fixture. \
Run `just write-config-schema` to overwrite with your changes.\n\n{diff}"
);
}
// 再写临时文件做精确文本比较,防止格式化或末尾换行无意漂移。
let tmp = TempDir::new().expect("create temp dir");
let tmp_path = tmp.path().join("config.schema.json");
write_config_schema(&tmp_path).expect("write config schema to temp path");
let tmp_contents = std::fs::read_to_string(&tmp_path)
.expect("read back config schema from temp path");
#[cfg(windows)]
let fixture = fixture.replace("\r\n", "\n");
#[cfg(windows)]
let tmp_contents = tmp_contents.replace("\r\n", "\n");
assert_eq!(
trim_single_trailing_newline(&fixture),
trim_single_trailing_newline(&tmp_contents),
"fixture should match exactly with generated schema"
);
}两阶段比较的失败含义不同:canonical diff 说明 schema 语义变了,精确文本 diff 说明仓库生成物没有按 确定格式提交。两者都通过才说明 fixture 可复现。
5.2 App Server契约
App Server 的 source of truth 是 Rust protocol types、ts-rs 标注、schemars 导出逻辑以及 experimental registry。稳定生成命令是:
just write-app-server-schema
just write-app-server-schema --experimental稳定模式会整体重建 schema/typescript/ 与 schema/json/,再把 TypeScript、公开 JSON schema 和 internal JSON schema 压缩到 stable precomputed export。experimental 模式在临时目录生成包含实验 API 的树,只更新 experimental precomputed export,避免实验字段混入稳定 vendored schema。
对应测试不仅比较内容,还比较完整文件集合;删除一个 Rust 类型却遗留旧 .ts 文件同样会失败。 JSON 比较会规范化 object key,并只在能够为所有元素构造稳定 key 时排序 array;TypeScript 比较会 归一 CRLF 和生成 banner,使 Windows 与 Unix 只对协议语义产生 diff。
5.3 Hook schema
Hook input/output 类型由 schemars 生成 21 个 JSON 文件:
just write-hooks-schemawrite_schema_fixtures() 会清空 hooks/schema/generated/ 再重建。运行时的 schema_loader.rs 使用 include_str! 把这些文件编译进二进制,并在首次加载时解析;测试则在临时 目录重新生成全部文件,与已提交版本逐一比较。这里的 schema 同时是发布契约和运行时资源,不是只 供文档展示。
5.4 Protobuf 生成源
少数内部协议同时保留 .proto 和生成的 .rs,例如 thread-config 与 exec-server relay。前者由 config/scripts/generate-proto.sh 调用 tonic_prost_build 写回 proto 目录;后者通过明确的 #[path = "proto/...rs"] 纳入模块,并被 Bazel target 列为源码。看到文件首行 @generated by prost-build 时,应回到 .proto 与对应生成入口修改,而不是手工维护字段编号。
6. Cargo 与 Bazel
Codex 不是“Cargo 项目附带一份 Bazel 文件”。日常 Rust 反馈以 Cargo/nextest 为主,CI 同时用 Bazel 验证 BUILD target、runfiles、跨平台依赖和发布构建。一个测试在 Cargo 通过,不代表它声明了 Bazel 需要的 binary、fixture 或 include_str! data。
6.1 just test语义
仓库不推荐直接运行 cargo test,本地统一入口是:
源码位置:justfile :: test
# no-fail-fast 让一次验证尽量暴露全部失败,RUST_MIN_STACK 统一测试线程栈。
test *args:
RUST_MIN_STACK=8388608 NEXTEST_PROFILE=local \
cargo nextest run --no-fail-fast "$@"源码位置:根 justfile :: test。--no-fail-fast 让一次运行尽量暴露所有失败;local profile 继承 default 配置。nextest 默认给失败测试重试一次,30秒判定一次 slow,连续两段后终止,并输出 JUnit。
并发并非越高越好。schema codegen、App Server subprocess、apply-patch CLI 和 Windows sandbox/process 测试分别进入受限 test group;本地 App Server 最多并发四个,Windows 重进程测试最多两个。这里的 串行化是资源隔离规则,不意味着被测代码只能串行工作。
源码位置:codex-rs/.config/nextest.toml :: profile.default, test-groups(节选)
[profile.default]
# 慢测试超时和一次retry属于执行策略,不改变测试断言本身。
slow-timeout = { period = "30s", terminate-after = 2 }
retries = 1
[profile.default.junit]
path = "junit.xml"
[profile.local]
inherits = "default"
[test-groups.app_server_protocol_codegen]
max-threads = 1
[test-groups.app_server_integration]
max-threads = 1
# 本地最多四个App Server子进程,避免资源争用造成伪超时。
[test-groups.app_server_integration_local]
max-threads = 4
[test-groups.core_apply_patch_cli_integration]
max-threads = 1
[test-groups.windows_sandbox_legacy_sessions]
max-threads = 1
[test-groups.windows_process_heavy]
max-threads = 26.2 CI验证层次
PR 的 blocking-ci.yml 汇总七类 required workflow:Bazel、blob size、cargo-deny、codespell、 repo checks、Rust CI 和 SDK。快速 Rust CI 根据改动路径选择 format、benchmark smoke、cargo-shear 和 argument-comment lint 等检查;SDK workflow 单独执行 Python 的 ruff/pytest 和 TypeScript 的 build/lint/Jest。
完整 nextest workflow 会先为目标平台建立 archive,再按 hash 分成四个 shard。Linux 与 Windows 还 单独构建 sandbox/helper binaries,并通过 CARGO_BIN_EXE_* 注入 archive 运行环境。平台矩阵覆盖 macOS arm64、Linux x64/arm64、Windows x64/arm64,并保存 Cargo timings 与 JUnit 报告。
这说明 nextest archive、helper staging 目录、timings 和 JUnit 都是 CI transport artifact;它们用来 把“编译”与“分片执行”解耦,不属于需要提交的生成物。
每个主要 job 末尾还调用 check-clean-worktree。任何测试或生成器若在 checkout 中留下 tracked diff 或普通 untracked file,job 都会失败。这能捕获“测试偷偷改了仓库”的问题,但生成物是否与源类型 一致仍主要由专用 fixture-match tests 保证。
7. 按改动选择
| 改动类型 | 最小行为测试 | 必须同步的资产 | 额外验证面 |
|---|---|---|---|
| 纯函数、解析器、序列化 | sibling unit test | 通常无 | 相关 crate just test -p |
| Agent Turn、工具或审批逻辑 | Core integration test | 模型/SSE fixture 仅按需 | 检查 request 与 event 两端 |
| App Server RPC | 公共 JSON-RPC integration test | README 与稳定/实验 schema | protocol crate test |
| TUI 可见输出 | TUI 行为测试 | 审阅并接受 .snap.new | 不同 viewport/状态路径 |
| apply-patch 规范 | portable scenario test | input/patch/expected | CLI 与平台路径语义 |
ConfigToml 或嵌套配置 | config schema test | core/config.schema.json | just write-config-schema |
| Hook wire type | Hook schema test | hooks/schema/generated/ | runtime embedded schema load |
| App Server 类型或 TS 标注 | schema fixture tests | TS、JSON、stable/experimental zst | stable/experimental filter |
.proto | 协议/relay tests | 对应 generated .rs | Cargo 与 Bazel compile |
| 测试中启动 workspace binary | integration test | BUILD data/deps 按需 | cargo_bin() 的 Cargo/Bazel 双路径 |
| SDK public API | pytest 或 Jest | SDK contract fixture 按需 | 真实 App Server smoke |
最小测试不是最少运行一个命令,而是选择能观察改动边界的测试。修改内部 parser 时无需启动完整 App Server;修改 Turn 工具回灌时,只测 parser 又覆盖不到真正风险。对于跨层改动,先跑受影响 crate 缩短反馈,再让完整 CI 覆盖 Bazel、SDK 和平台矩阵。
8. 失败产物定位
| 失败表现 | 它通常说明什么 | 不应立即做什么 |
|---|---|---|
普通 assert_eq diff | 行为或结构对象变化 | 拆成大量字段断言掩盖差异 |
.snap.new 出现 | 可见输出与已接受契约不同 | 未审阅就全量 accept |
| fixture 最终目录不等 | 规范场景、输入或实现至少一项改变 | 从实际输出自动覆盖 expected |
| schema 文件集合不等 | 类型新增/删除与 vendored tree 漂移 | 只删当前报错的单个文件 |
| stable schema 含实验字段 | experimental filter/标注错误 | 把实验字段手改出 JSON |
| Cargo 通过、Bazel 找不到资源 | BUILD data 或 runfiles 解析缺失 | 硬编码 target/ 路径 |
| nextest 本地偶发通过、CI 超时 | 共享资源、进程数或平台条件问题 | 无限增加 retry 掩盖竞态 |
| clean-worktree 失败 | 测试/生成步骤留下文件或 drift | 忽略 untracked 文件继续发布 |
| SDK contract test 失败 | Rust wire schema 与客户端公开 API 不一致 | 只修客户端类型而不核对 source of truth |
阅读测试失败时,应沿“source → harness → input asset → observed output → expected result”反向 定位。测试代码决定观察点,fixture 决定输入,snapshot/schema 决定预期;只有先确认这三个角色,才 能判断应该修实现、修测试,还是运行生成器同步派生产物。
9. 仓库资产统计
以下命令从当前源码目录和仓库文件列表读取统计结果。它们不把 target/ 或其他本地产物当成源码资产。
# 含#[cfg(test)]或mod tests标记的Rust文件;这是“文件数”,不是测试函数数。
rg -l '#\[cfg\(test\)\]|mod tests' codex-rs --glob '*.rs' | wc -l
# tests/suite与fixture中的受跟踪文件。
git ls-files 'codex-rs/**/tests/suite/*.rs' | wc -l
git ls-files 'codex-rs/**/fixtures/**' | wc -l
# 全仓库snapshot、TUI snapshot以及未接受的新snapshot。
git ls-files | rg '\.snap$' | wc -l
git ls-files 'codex-rs/tui/**' | rg '\.snap$' | wc -l
git ls-files | rg '\.snap\.new$' | wc -l
# Hook和App Server的受跟踪schema文件。
git ls-files 'codex-rs/hooks/schema/generated/*.json' | wc -l
git ls-files 'codex-rs/app-server-protocol/schema/typescript/**' | wc -l
git ls-files 'codex-rs/app-server-protocol/schema/json/**' | wc -l| 统计项 | 结果 | 口径限制 |
|---|---|---|
| 有测试模块标记的 Rust 文件 | 1138 | 一个文件可含多个或零个实际 #[test] |
tests/suite/*.rs | 300 | 不含近场 unit test 与其他命名集成入口 |
| fixture 文件 | 97 | 只统计路径包含 fixtures/ 的受跟踪文件 |
全仓库 / TUI *.snap | 759 / 705 | snapshot 数不等于测试数 |
*.snap.new | 0 | 只说明当前目录没有新的 snapshot 文件 |
| Hook generated JSON | 21 | 由事件输入/输出组合决定,不等于Hook事件数 |
| App Server TS / JSON schema | 688 / 295 | 文件数不等于RPC method数 |
这些命令适合比较版本或快速了解资产规模,不适合衡量 statement、branch 或行为覆盖率。若要统计 Cargo 明确 test target,应 改用 Cargo 工作空间全景 的 metadata 查询;当前源码中约有 32 个 package 包含显式 test target,但仍不含 library 内联测试。
10. 资产地图与专题
| 改动落点 | 先进入的正文 | 最小验证入口 |
|---|---|---|
| Thread/Turn、Task、关闭 | 运行时任务拓扑、Session关闭流程 | core/tests/all.rs 与 TestCodexBuilder |
| App Server RPC、握手、背压 | Codex 产品形态全景、CodexThread背压 | app-server/tests/all.rs 与 TestAppServerBuilder |
| 对象和历史投影 | 核心数据对象关系 | protocol projection tests 与 rollout fixture |
| 文件、网络、平台sandbox | Codex信任边界、跨平台能力矩阵 | policy unit test+目标平台fixture |
| feature与设置约束 | Core运行时能力开关、Session设置约束 | config tests+schema fixture |
| 不确定选哪个harness | Codex源码阅读路线 | 文末 TestCodex / TestAppServer 完成检查 |
完成测试地图阅读的标志,是已经找到能够因目标行为变化而失败的测试或生成物比较。只指出文件数量、snapshot 目录或 CI workflow 名称,还不足以解释行为。
