--- last_reviewed: 2026-10-19 --- # tests — 单元测试 pytest 运行(`make test` 带覆盖率)。当前 148 例。 | 文件 | 覆盖范围 | |------|---------| | `test_config.py` | 配置加载:默认值、文件覆盖、环境变量优先级 | | `test_invoice.py` | 发票常量、差旅判定、批量分类 | | `test_matcher.py` | 金额匹配:容差、一对一、一对多贪心、未匹配、CSV 汇总构造 | | `test_mcp_analysis.py` | MCP 分析工具:缓存分组、凑额复核、业务约束违反、无发票场景、`save_info` 剥离多余字段、 草稿不落盘、`rules_get` 形状、`info_skeleton` 与规则同源、骨架填满即通过 | | `test_requisition.py` | 申购明细:品名清洗、规格猜测、发票号去重、关键词排除、项目名取值链与回退 | | `test_mcp_browser.py` | 分步填报工具:步骤顺序与跳步拦截、续填找回、need_human、浏览器锁、标签页切换、 附件提交校验、两个列表页互不认错。用 FakePage 跑 `base.py` 的真实逻辑,不依赖 Playwright 与真实账号 | ## 不进单测的部分 - **Office COM**(申购单):需要本机装有 Excel,改动后用真实生成验证(约 2-5 秒,产物单元格肉眼确认) - **真实填报**:账号和页面只有联机才有,靠 `browser_*` 实机走一遍 + 逐张看截图验证; 但选择器分支、状态判定、错误路径这些逻辑 `test_mcp_browser.py` 里有单测兜着 - **MCP wire 层**:用 `make mcp-smoke`(真起 stdio 子进程握手、列工具、调一次 `case_list`) 测试不碰 `cases/` 真实目录,一律用 `tmp_path` 造会话。