|
|
@@ -62,43 +62,221 @@ python -m pytest utils_test/Completeness_Test/test_completeness_accuracy.py::Tes
|
|
|
| acceptance | 5 | 5 | 24 | 19 | 20.8% |
|
|
|
| other | 4 | 2 | 21 | 19 | 9.5% |
|
|
|
|
|
|
-## 关键验证逻辑
|
|
|
+## 测试逻辑与统计准确性说明
|
|
|
|
|
|
-### 1. 误报检测逻辑
|
|
|
+### 1. 核心测试原理(集合论验证)
|
|
|
+
|
|
|
+测试基于**集合交集原理**验证统计准确性:
|
|
|
+
|
|
|
+```
|
|
|
+设:
|
|
|
+- A = 实际存在的分类集合(从 chunks 提取)
|
|
|
+- B = 检查器报告的缺失分类集合
|
|
|
+
|
|
|
+若 A ∩ B = ∅(空集),则证明:
|
|
|
+✓ 所有实际存在的分类都没有被误报为缺失
|
|
|
+✓ 检查器的统计逻辑正确
|
|
|
+```
|
|
|
+
|
|
|
+#### 为什么这种方法有效?
|
|
|
+
|
|
|
+| 条件 | 数学表达 | 含义 |
|
|
|
+|-----|---------|------|
|
|
|
+| 无误报 | A ∩ B = ∅ | 实际存在的分类与报告缺失的分类无交集 |
|
|
|
+| 有遗漏 | B - A ≠ ∅ | 报告缺失的分类中,部分是真正缺失的 |
|
|
|
+| 完全正确 | A ∪ B = 标准集 | 实际存在 + 真正缺失 = 标准分类全集 |
|
|
|
+
|
|
|
+### 2. 误报检测逻辑(核心测试代码)
|
|
|
|
|
|
```python
|
|
|
-# 获取实际存在的分类
|
|
|
-actual_tertiary = {...}
|
|
|
+def test_no_false_positives_for_existing_categories():
|
|
|
+ """
|
|
|
+ 关键测试:确保存在的分类不会被误报为缺失
|
|
|
+
|
|
|
+ 验证逻辑:
|
|
|
+ 1. 从测试数据中提取所有实际存在的三级分类 → actual_tertiary
|
|
|
+ 2. 调用完整性检查器获取报告缺失的分类 → reported_missing
|
|
|
+ 3. 计算交集:false_positives = reported_missing & actual_tertiary
|
|
|
+ 4. 断言:交集必须为空,否则存在误报
|
|
|
+ """
|
|
|
+ # 步骤1:提取实际存在的分类(直接从测试数据JSON中提取)
|
|
|
+ actual_tertiary = {
|
|
|
+ (chunk["chapter_classification"],
|
|
|
+ chunk["secondary_category_code"],
|
|
|
+ chunk["tertiary_category_code"])
|
|
|
+ for chunk in test_chunks
|
|
|
+ if chunk["tertiary_category_code"] not in ["", "none", "non_standard"]
|
|
|
+ }
|
|
|
+
|
|
|
+ # 步骤2:调用检查器获取报告结果
|
|
|
+ result = await checker.check(chunks=chapter_chunks, ...)
|
|
|
+ reported_missing = {
|
|
|
+ (item["first_code"], item["secondary_code"], item["tertiary_code"])
|
|
|
+ for item in result["missing_details"]
|
|
|
+ }
|
|
|
|
|
|
-# 获取检查器报告的缺失项
|
|
|
-reported_missing = {...}
|
|
|
+ # 步骤3:计算交集(潜在的误报)
|
|
|
+ false_positives = reported_missing & actual_tertiary
|
|
|
|
|
|
-# 计算交集(误报)
|
|
|
-false_positives = reported_missing & actual_tertiary
|
|
|
+ # 步骤4:验证无交集(核心断言)
|
|
|
+ assert len(false_positives) == 0, f"存在 {len(false_positives)} 个误报: {false_positives}"
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 数据流验证流程
|
|
|
|
|
|
-# 验证无交集
|
|
|
-assert len(false_positives) == 0, f"存在 {len(false_positives)} 个误报"
|
|
|
+```
|
|
|
+┌─────────────────────────────────────────────────────────────────────────┐
|
|
|
+│ 测试数据准备阶段 │
|
|
|
+├─────────────────────────────────────────────────────────────────────────┤
|
|
|
+│ 测试JSON文件 │
|
|
|
+│ ↓ │
|
|
|
+│ 提取 chunks → 遍历每个块的分类字段 │
|
|
|
+│ ↓ │
|
|
|
+│ 构建 actual_tertiary 集合(真实存在的分类) │
|
|
|
+│ 格式: {(一级, 二级, 三级), ...} │
|
|
|
+└─────────────────────────────────────────────────────────────────────────┘
|
|
|
+ ↓
|
|
|
+┌─────────────────────────────────────────────────────────────────────────┐
|
|
|
+│ 检查器执行阶段 │
|
|
|
+├─────────────────────────────────────────────────────────────────────────┤
|
|
|
+│ 调用 LightweightCompletenessChecker.check() │
|
|
|
+│ ↓ │
|
|
|
+│ 检查器内部逻辑: │
|
|
|
+│ 1. 从CSV加载标准分类表 │
|
|
|
+│ 2. 统计 chunks 中实际存在的分类(present_set) │
|
|
|
+│ 3. 计算缺失:missing = standard - present │
|
|
|
+│ ↓ │
|
|
|
+│ 返回 reported_missing 集合(报告缺失的分类) │
|
|
|
+└─────────────────────────────────────────────────────────────────────────┘
|
|
|
+ ↓
|
|
|
+┌─────────────────────────────────────────────────────────────────────────┐
|
|
|
+│ 验证断言阶段 │
|
|
|
+├─────────────────────────────────────────────────────────────────────────┤
|
|
|
+│ 计算:false_positives = actual_tertiary ∩ reported_missing │
|
|
|
+│ ↓ │
|
|
|
+│ 断言:assert len(false_positives) == 0 │
|
|
|
+│ ↓ │
|
|
|
+│ 若通过:✓ 检查器统计正确,无误报 │
|
|
|
+│ 若失败:✗ 列出误报项,测试失败 │
|
|
|
+└─────────────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
-### 2. 分类提取逻辑
|
|
|
+### 4. 分类提取逻辑
|
|
|
|
|
|
```python
|
|
|
-# 从 chunks 中提取三级分类
|
|
|
-cat1 = chunk.get("chapter_classification")
|
|
|
-cat2 = chunk.get("secondary_category_code")
|
|
|
-cat3 = chunk.get("tertiary_category_code")
|
|
|
-
|
|
|
-# 排除无效值
|
|
|
-if cat3 and cat3 not in ["", "none", "non_standard"]:
|
|
|
- actual.add((cat1, cat2, cat3))
|
|
|
+# 从 chunks 中提取三级分类(测试代码侧)
|
|
|
+def extract_actual_categories(chunks):
|
|
|
+ result = {"tertiary": set(), "secondary": set()}
|
|
|
+
|
|
|
+ for chunk in chunks:
|
|
|
+ cat1 = chunk.get("chapter_classification") # 一级:章节代码
|
|
|
+ cat2 = chunk.get("secondary_category_code") # 二级:二级分类代码
|
|
|
+ cat3 = chunk.get("tertiary_category_code") # 三级:三级分类代码
|
|
|
+
|
|
|
+ if not cat1 or not cat2:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 记录二级分类
|
|
|
+ result["secondary"].add((cat1, cat2))
|
|
|
+
|
|
|
+ # 记录三级分类(排除无效值)
|
|
|
+ if cat3 and cat3 not in ["", "none", "non_standard"]:
|
|
|
+ result["tertiary"].add((cat1, cat2, cat3))
|
|
|
+
|
|
|
+ return result
|
|
|
```
|
|
|
|
|
|
+### 5. 统计准确性验证维度
|
|
|
+
|
|
|
+| 验证维度 | 测试方法 | 通过标准 |
|
|
|
+|---------|---------|---------|
|
|
|
+| **无误报** | 集合交集验证 | `actual ∩ missing = ∅` |
|
|
|
+| **统计一致性** | 数值等式验证 | `total == present + missing` |
|
|
|
+| **二级统计** | 逐章节验证 | 每个二级分类的统计满足等式 |
|
|
|
+| **结构完整** | 字段存在性检查 | 结果包含所有必需字段 |
|
|
|
+| **边界处理** | 无效值过滤 | `none`, `non_standard`, 空值正确处理 |
|
|
|
+
|
|
|
## 测试结果
|
|
|
|
|
|
-- **测试状态**: 全部通过
|
|
|
+- **测试状态**: 全部通过 ✅
|
|
|
- **误报情况**: 0个
|
|
|
+- **测试覆盖率**: 9个测试用例,覆盖所有关键场景
|
|
|
- **结论**: 完整性审查模块工作正常,没有出现"分类结果中存在但被误报为缺失"的情况
|
|
|
|
|
|
+### 测试执行示例(关键测试)
|
|
|
+
|
|
|
+```bash
|
|
|
+$ python -m pytest test_completeness_accuracy.py::TestCompletenessAccuracy::test_no_false_positives_for_existing_categories -v -s
|
|
|
+
|
|
|
+============================================================ test session starts ============================================================
|
|
|
+test_completeness_accuracy.py::TestCompletenessAccuracy::test_no_false_positives_for_existing_categories
|
|
|
+==============================================================
|
|
|
+测试章节: basis
|
|
|
+ chunks 数量: 5
|
|
|
+ 实际存在的三级分类: 5 个
|
|
|
+ 报告缺失的三级分类: 11 个
|
|
|
+ 完整率: 31.2%
|
|
|
+ [OK] 该章节无分类误报
|
|
|
+
|
|
|
+==============================================================
|
|
|
+测试章节: overview
|
|
|
+ chunks 数量: 7
|
|
|
+ 实际存在的三级分类: 6 个
|
|
|
+ 报告缺失的三级分类: 10 个
|
|
|
+ 完整率: 37.5%
|
|
|
+ [OK] 该章节无分类误报
|
|
|
+
|
|
|
+...(其他章节类似输出)
|
|
|
+
|
|
|
+==============================================================
|
|
|
+测试章节: other
|
|
|
+ chunks 数量: 4
|
|
|
+ 实际存在的三级分类: 2 个
|
|
|
+ 报告缺失的三级分类: 19 个
|
|
|
+ 完整率: 9.5%
|
|
|
+ [OK] 该章节无分类误报
|
|
|
+
|
|
|
+PASSED
|
|
|
+```
|
|
|
+
|
|
|
+### 测试执行示例(详细报告)
|
|
|
+
|
|
|
+```bash
|
|
|
+$ python -m pytest test_completeness_accuracy.py::TestCompletenessAccuracy::test_completeness_accuracy_report -v -s
|
|
|
+
|
|
|
+==============================================================
|
|
|
+完整性审查准确性测试报告
|
|
|
+==============================================================
|
|
|
+
|
|
|
+[测试数据概览]
|
|
|
+ - 文档总块数: 65
|
|
|
+ - 涉及章节数: 9
|
|
|
+ - 二级分类数: 35
|
|
|
+ - 三级分类数: 40
|
|
|
+
|
|
|
+[各章节详细统计]
|
|
|
+
|
|
|
+ 章节: basis
|
|
|
+ - 块数: 5
|
|
|
+ - 存在分类: 5
|
|
|
+ - 标准分类: 16
|
|
|
+ - 缺失: 11
|
|
|
+ - 完整率: 31.2%
|
|
|
+
|
|
|
+...(其他章节统计)
|
|
|
+
|
|
|
+[验证结果汇总]
|
|
|
+ [OK] 所有章节的分类代码匹配正确
|
|
|
+ [OK] 无分类误报情况
|
|
|
+ [OK] 统计数据一致性正确
|
|
|
+
|
|
|
+[结论]
|
|
|
+ 完整性审查模块工作正常,没有出现
|
|
|
+ '分类结果中存在但被误报为缺失'的情况
|
|
|
+==============================================================
|
|
|
+PASSED
|
|
|
+```
|
|
|
+
|
|
|
## 注意事项
|
|
|
|
|
|
1. **测试数据依赖**: 测试依赖于 `temp/construction_review/final_result/` 目录下的JSON文件
|