Files
2026Technology-Competition/docs/superpowers/specs/2026-08-09-error-code-consistency-test-design.md
T

5.3 KiB
Raw Blame History

错误码一致性测试设计(api-design §7 ↔ exceptions.py

状态: 已批准(brainstorming + DX 审查吸收) 日期: 2026-08-09 里程碑后备路径: LLM 错误码对齐(error_code)收尾

1. 背景与目标

「LLM 错误码对齐」完成后,api-design.md §7 错误码表与 src/genesis/inference/exceptions.py 的异常树通过 error_code 类属性建立了一一对应关系(LLM_TIMEOUT ↔ LLMTimeoutError 等),但该对应关系目前仅靠人工核对维护:

  • test_inference_errors.py 断言了异常类自身的 error_code 值(代码自证代码,防不了文档漂移)
  • 文档添加/删除错误码行、或代码新增异常类时,没有测试会在两边失配时变红

目标: 将「api §7 = 唯一事实源」的核对从人工升级为机器验证——新增回归测试解析 docs/api-design.md §7 表格,断言与异常树双向一致,防文档↔代码漂移。

2. 范围与不做的事

范围:

  • 仅验证 §7 表格中来源列以 exceptions. 开头的 4 条 LLM 错误码行(LLM_TIMEOUT / LLM_NETWORK_ERROR / LLM_NOT_CONFIGURED / LLM_PARSE_ERROR
  • 双向验证:异常树 → 文档、文档 → 异常树

不做(YAGNI):

  • 不验证非 LLM 错误码行(FILE_TYPE_INVALID、EMBEDDING_FAILED、INTERNAL_ERROR 等来源列为「—」,暂无代码映射)
  • 不抽 src 生产模块(测试自包含,零生产代码改动)
  • 不做 web-ui §8 端点表等其它文档一致性检查(有第二个需求再提炼共享模块)

3. 设计

3.1 落点

新建独立测试文件 tests/test_api_design_consistency.py(单一职责:文档 ↔ 代码一致性门禁),不污染现有 test_inference_errors.py

3.2 文件定位(沿用项目先例)

API_DOC = Path(__file__).resolve().parents[1] / "docs/api-design.md"

(与 tests/test_real_samples.py:7SAMPLES 定位方式一致;不依赖 CWD,pytest 任意目录启动可跑。)

3.3 解析函数(内联纯函数)

def _extract_llm_error_rows(document: str) -> dict[str, str]:
    """解析 §7 表格中来源列以 exceptions. 开头的行,返回 {错误码: 来源类名}。"""
  • 实现:逐行匹配表格行 | \CODE` | ... | exceptions.Xxx |`,提取错误码与来源类名
  • 用途:返回 LLM 错误码 → 来源异常类名 的映射;非 LLM 行(来源 "—")被天然排除

3.4 测试用例(4 个)

# 用例 验证方向 断言要点
1 test_error_doc_lists_every_llm_error_code 异常树 → 文档 遍历 LLMError.__subclasses__(),每个子类 error_code(非 None)必须出现在文档映射中,且来源类名 == 子类名
2 test_error_doc_llm_rows_resolve_to_exception 文档 → 异常树 文档映射中每个错误码都能在 LLMError.__subclasses__() 中找到 error_code 相同、类名匹配的唯一类
3 test_error_doc_stable_llm_row_count 格式护栏 文档映射中 LLM 行数 == 4(防止表格结构变化静默失效;新增/删除 LLM 行需显式更新此数)
4 test_error_doc_parse_guard_prevents_silent_noop 格式护栏 若解析结果为空(表格格式被改动导致正则失配),立即硬失败而非静默通过

3.5 失败可诊断(DX 修正 F1/F2)

  • 测试 1/2 断言失败时,输出双向差异清单:文档有而代码无的码、代码有而文档无的码,并附引导语「请同步 api-design.md §7 或 exceptions.py」
  • 通过 pytest 的断言消息(assert ... , "差异说明")实现,避免裸 assert 'LLM_QUOTA' in dict 的模糊失败

3.6 契约可读性(DX 修正 F4

  • 文件头部模块 docstring 写明:「此测试为 api-design §7 ↔ exceptions.py 的机器契约,变更错误码必须两处同步修改」

4. 错误处理

场景 行为
文档缺失 read_text() 抛 FileNotFoundError → 测试失败(显式暴露)
表格行解析失配(0 行) 用例 4 硬失败,杜绝静默失效
新增异常未登记 / 文档多行无单码 用例 1/2 分别双硬失败并列出差异
LLM 行数变化 用例 3 失败,提示显式更新计数

5. 测试策略与覆盖

  • 本功能自身即测试;不新增生产代码,fail_under=99 红线不受触碰(其按 src/ 生效,tests/ 命中不计)
  • 全量回归保持 ≥ 128 passed(新增 4 用例后 ≥ 132
  • 验证命令:python -m pytest tests/test_api_design_consistency.py -v(聚焦);python -m pytest -q(全量)

6. 验收标准

  1. pytest tests/test_api_design_consistency.py -v 全绿(4 passed
  2. 全量回归 python -m pytest -q ≥ 132 passed / 100.00% 覆盖
  3. 手工破坏验证(可选):临时删除文档某 LLM 行 → 用例 1 变红且差异清单可读;恢复正常
  4. 不修改任何现有源文件或测试文件

7. 影响面

  • 新增 1 个测试文件(约 60-80 行)
  • 修改 1 个文件:_AI_USAGE_LOG.md(追加日志行)
  • 提交消息:test: api §7 与异常树错误码一致性门禁测试(防文档漂移)

8. 不做的事(YAGNI 最终确认)

  • 非 LLM 行验证
  • src 生产辅助模块
  • Enum 化错误码(spec 已明确 str)
  • 其它文档表一致性检查