测试¶
测试套件位于 tests/(在 pplx_export 包之外),完全离线运行——所有输入数据随仓库提交于 tests/fixtures/,没有任何测试触碰网络或真实的用户级配置。本页说明如何运行套件、套件结构以及如何新增测试。机制视角(快照回归如何与渲染器的幂等承诺互锁)见测试系统架构;输入数据本身见测试 fixtures。
运行测试¶
uv run pytest tests
pytest 是已声明的开发依赖,uv run 无需额外安装即可使用。可依赖的保证:
- 零网络——原始 API 抓取随仓库提交;在线代码路径一律通过离线重渲或
tmp_path/monkeypatch构造来覆盖。 - 不读真实用户配置——一个 autouse fixture(
tests/conftest.py:40-53)加载占位符账户配置(alice/bob,与config.example.toml对齐),因此结果绝不依赖真实的~/.config。 - 快——300+ 用例约一秒跑完;用例数随回归补充持续增长。
实用筛选:
| 命令 | 作用 |
|---|---|
uv run pytest tests |
运行整个套件 |
uv run pytest tests/test_units.py |
运行单个文件 |
uv run pytest tests -k snapshot |
只运行名字匹配 snapshot 的测试 |
uv run pytest tests -x -q |
首个失败即停,静默输出 |
套件结构¶
套件分为三个家族:
- 渲染快照测试——
test_render_snapshots.py:从 fixture 原始 JSON 经 normalize → parse → render 的全链路回归,与随仓库提交的 golden 快照逐字节比对。覆盖全部五种模式(search / deep-research / computer / council / study)及裁剪缺陷场景。 - 单元测试——
test_units.py与各专题文件:状态、节流、增量规划、规范化与维护命令的类/函数级行为。 - 修复回归文件——
test_fix_*.py:每个外部评审发现一个文件(N-xx / V3-xx / V4-xx / V5-xx);文件头 docstring 复述该发现,测试钉住修复后的行为。
| 文件 | 覆盖 |
|---|---|
conftest.py |
公共 fixture:render_fixture / rendered;占位符用户配置 |
test_render_snapshots.py |
渲染快照回归:五模式全线程 fixtures + 裁剪缺陷场景;与 golden 逐字节比对;dict-repr 残留特征检查 |
test_units.py |
BatchState(尾零归一化、过期终态、损坏备份)、Throttle(退避公式/上限/重置)、plan_incremental、AssetDownloader._final_name、normalize_math_delims、TestDetectMode、TestSafeFolder、TestFetchMissingBlocks、TestExternalReviewFixes |
test_interruptions.py |
中断语义:classify_wf_status 五分类、归属瀑布 ③ 附录、渲染标注、中断登记 |
test_stub_workflows.py |
残桩轮关联:match_stub_workflows(10 秒时间窗、单次消费、锚定排除)、render_wf_item 嵌套渲染递归/去重守卫 |
test_relations.py |
relations 图:same_prompt / references / subagent_of 边构造 |
test_search_mode_backfill.py |
search-mode-backfill:具体度优先级、保留原值、幂等续跑、索引合并 |
test_sync_deleted.py |
sync-deleted 状态机:跨账户候选判定、终态处理 |
test_answer_variants.pytest_answer_variant_logging.py |
answer_variants 检测链与 ANSWER_VARIANT_DETECTED jsonl 日志 |
test_config_external.py |
用户级外置配置:加载优先级、缺文件降级、resolve_cli_account |
test_fix_n01…n11_*.py(9 个文件) |
第二轮评审回归(N-01..N-12) |
test_fix_v301_*.py / test_fix_v305_*.py |
第三轮评审回归(V3-01 / V3-05) |
test_fix_v4*.py |
第四轮评审回归(V4-01..V4-06) |
test_fix_v5_review.py |
第五轮评审回归(V5-01..V5-10) |
快照测试如何复用生产重渲路径¶
快照测试不含任何重新实现的管线——它直接调用生产渲染器:
render_fixture(tests/conftest.py:56-68)把 fixture 的原始 JSON(raw_entries.json/raw_blocks.json/thread.json)复制进临时目录,并调用rerender(pplx_export/commands/rerender_cmd.py:105)——即pplx-export re-render命令在生产中运行的同一函数。renderedfixture(tests/conftest.py:71-78)是个工厂:rendered("search_demo")返回(重渲后的线程目录, fixtures 里的 golden 目录),测试随后逐字节 diffconversation.md与每个turns/turn_*.md。- 由于 golden 也经同一条离线路径重生成(见测试 fixtures),测试始终用渲染器的最新输出对比已提交产物:任何改变产物字节的渲染层变更都会让套件变红——与重渲的幂等承诺互锁。
除逐字节相等外,test_render_snapshots.py 还钉住了内容不变式:答案绝不是空占位符 (无);dict-repr 残留特征({'type': ... 泄漏进渲染文本)直接判失败。
如何新增测试¶
- 现有逻辑的单元测试——向对应的专题文件添加
test_*函数(或在test_units.py中加一个Test*类)。使用tmp_path/monkeypatch;绝不触网,绝不读真实的~/.config(占位符配置是 autouse 的)。 - 缺陷修复的回归——新建
tests/test_fix_<round><nn>_<slug>.py,文件头 docstring 复述发现(旧行为 → 修复后行为),随后钉住修复后的行为。像现有test_fix_*文件一样,在tmp_path中直接构造原始 JSON。 - 渲染回归——需要一个 fixture:在
tests/fixtures/下新增(或裁剪)一个,用维护工具刷新其 golden(见测试 fixtures),然后要么把目录名加入test_render_snapshots.py的FULL/SCENARIOS,要么写一个消费renderedfixture 的专用test_*函数做场景级断言。
遵循既有风格:类型标注、from __future__ import annotations,以及与相邻文件一致的双语模块 docstring。
另见¶
- 测试 fixtures——套件所依赖的合成原始抓取与 golden 快照
- 测试系统架构——套件背后的回归策略
- 离线操作——快照测试所复用的生产重渲管线