test: 覆盖率提升至 100%(fail_under 90→99,13 个防御/边界用例)

This commit is contained in:
lhl
2026-08-09 04:49:29 +08:00
parent 737911cf25
commit 2fbff07d3f
10 changed files with 180 additions and 46 deletions
+37 -38
View File
@@ -3,58 +3,57 @@
- 日期:2026-08-09
- 工具:`pytest-cov` 7.1.0 / `coverage` 7.15.4
- 范围:`src/genesis`(排除 tests 自身)
- 阈值:`fail_under = 90``pyproject.toml` `[tool.coverage.report]`),未达标时 pytest 退出码非 0
- 全量用例:**58 passed,无 skip**
- 阈值:`fail_under = 99``pyproject.toml` `[tool.coverage.report]`),未达标时 pytest 退出码非 0
- 全量用例:**71 passed,无 skip**
- 输出:终端摘要(`--cov-report=term-missing`)、HTML`htmlcov/index.html`,已 .gitignore
## 总览
| 指标 | 值 |
|------|-----|
| 语句总数 | 571 |
| 未覆盖语句 | 12 |
| 分支总数 | 150 |
| 未覆盖分支 | 12 |
| **总覆盖率** | **96.67%** |
| 最低模块 | `table_extractor.py` 88% |
| 最高模块 | 9 个文件 100% |
| 语句总数 | 563(含 pragma 排除的不可达防御分支) |
| 未覆盖语句 | 0 |
| 分支总数 | 140 |
| 未覆盖分支 | 0 |
| **总覆盖率** | **100.00%** |
## 分模块
## 分模块(全部 100%
| 模块 | Stmts | Miss | Branch | BrPart | Cover | 未覆盖行 |
|------|------:|-----:|-------:|-------:|------:|----------|
| `__init__.py` | 1 | 0 | — | — | 100% | — |
| `data_models.py` | 180 | 0 | | | 100% | — |
| `excel_reader.py` | 12 | 0 | 2 | 0 | 100% | — |
| `free_text_extractor.py` | 22 | 0 | 10 | 0 | 100% | — |
| `merge_fill.py` | 15 | 0 | 10 | 0 | 100% | — |
| `paragraph_splitter.py` | 17 | 0 | 10 | 0 | 100% | — |
| `provenance.py` | 2 | 0 | | | 100% | — |
| `sheet_detector.py` | 20 | 0 | 14 | 0 | 100% | — |
| `config.py` | 128 | 1 | 24 | 1 | 99% | 134 |
| `sheet_nature.py` | 33 | 2 | 18 | 3 | 90% | 26, 32, 40→44 |
| `table_extractor.py` | 24 | 2 | 10 | 2 | 88% | 32, 37 |
| `formatting_detector.py` | 40 | 3 | 20 | 2 | 92% | 1516, 22, 31→33 |
| `excel_parser.py` | 77 | 4 | 32 | 4 | 93% | 3637, 61, 66→65, 100 |
| 模块 | Stmts | Miss | Branch | BrPart | Cover |
|------|------:|-----:|-------:|-------:|------:|
| `__init__.py` | 1 | 0 | — | — | 100% |
| `config.py` | 128 | 0 | 24 | 0 | 100% |
| `data_models.py` | 180 | 0 | | | 100% |
| `parsers/excel_parser.py` | 73 | 0 | 28 | 0 | 100% |
| `parsers/excel_reader.py` | 12 | 0 | 2 | 0 | 100% |
| `parsers/formatting_detector.py` | 40 | 0 | 20 | 0 | 100% |
| `parsers/free_text_extractor.py` | 22 | 0 | 10 | 0 | 100% |
| `parsers/merge_fill.py` | 15 | 0 | 10 | 0 | 100% |
| `parsers/paragraph_splitter.py` | 17 | 0 | 10 | 0 | 100% |
| `parsers/provenance.py` | 2 | 0 | | | 100% |
| `parsers/sheet_detector.py` | 20 | 0 | 14 | 0 | 100% |
| `parsers/sheet_nature.py` | 29 | 0 | 12 | 0 | 100% |
| `parsers/table_extractor.py` | 24 | 0 | 10 | 0 | 100% |
## 未覆盖点说明(12 语句 + 12 分支
## 达到 100% 的补充(相对首次基线 96.67%
主要未覆盖区域属于防御分支 / 异常路径
新增 13 个防御/边界用例覆盖了此前未触达的分支
- `config.py:134``unset(_env)` 分支(枚举加载外的环境变量消除路径)
- `sheet_nature.py:26/32` — 空白行修正 / `value` 缺失兜底
- `table_extractor.py:32/37``column_letter` 越界兜底 / 空列头兜底
- `formatting_detector.py:15-22` — 非法 RGB 字符串剔除分支
- `excel_parser.py:36-37,61,100` — 空表跳过、`header_row<0` 回落、无表头 free_text 直接文本化
均为「非法输入 / 防御分支」,非主路径;当前 96.67% 已满足红线 90%。
- `test_sheet_nature.py`:空矩阵→FREE_TEXT、稀疏多列(非空占比<0.7)→FREE_TEXT、有表头无 ・/■ 行→TABLE
- `test_table_extractor.py`:空矩阵→空表、`header_row` 越界/负值回落 0
- `test_formatting_detector.py`:6/8 位十六进制接受、纯黑/主题色/非法 hex/长度不足/访问异常→None、仅背景色命中、`fill=None` 防御分支
- `test_config.py``_expand_env` 的 list 分值(列表内递归展开占位)
- `test_excel_parser.py`:空 sheet→skipped、碎片段格式不污染表格段 `seg_fmt_map`66→65
- pragma 标注两处不可达防御分支:`excel_parser` 两处 `header_row<0` 回落(`classify_sheet==TABLE` 恒有表头)、`sheet_nature``header_row>=0` 检测(`_free_text_like()==False` 恒含表头)
## 门槛策略
- `pyproject.toml` 已固化 `fail_under = 90`含 12 个 `branch` 分支统计)
- 每次 `python -m pytest` 默认附带覆盖率检查;未来若引入重业务逻辑(LLM/Writer 里程碑),可将 `fail_under` 抬至 95~98 并补充新用例
- `fail_under = 99`余量 1%):未来若引入未测的新模块/分支(LLM 结构化、Writer 等),需为新代码补测试或显式 `# pragma: no cover` 标注不可达防御分支,否则 CI 拦截
- 每次 `python -m pytest` 默认附带覆盖率检查
- 报告归档:本文件(docs/+ HTMLhtmlcov/,不纳入 git
## 后续可选增强(非当前阻塞)
-`fail_under` 提升至 95% 时需补上述 12 行(多为防御分支,成本低)
- 可在 CI 中将 `--cov-report=html` 或 junit/xml 纳入流水线归档
-`fail_under` 保持 99 并作为 CI 红线
- 对 LLM 相关(InferenceEngine)等后续模块按同样标准配置覆盖率
- 可将 HTML 报告接入 CI artifact 归档