WangXuMing 1d6ea21bd8 fix (sgsc-完整性审查):接入主流程 3 тижнів тому
..
README.md 525cd8e294 v0.0.8-doc更改 1 місяць тому
test_completeness_accuracy.py 1d6ea21bd8 fix (sgsc-完整性审查):接入主流程 3 тижнів тому

README.md

完整性审查准确性验证测试

测试目的

验证完整性审查模块(completeness_reviewer.py)是否正确统计分类结果, 确保不会出现"分类结果中存在,但被误报为缺失"的情况

测试数据

  • 来源文件: temp/construction_review/final_result/67d45692fb97aeef8f896e78475ce539-1773153034.json
  • 数据内容: 包含65个已分类的文档块(chunks)
  • 分类维度: 一级分类(chapter_classification)、二级分类(secondary_category_code)、三级分类(tertiary_category_code)

测试用例列表

测试用例 说明 关键验证点
test_data_file_exists 测试数据文件存在性检查 数据文件可访问
test_standard_csv_exists 标准CSV文件存在性检查 标准分类表可访问
test_extract_actual_categories 测试分类提取功能 正确提取实际存在的分类
test_no_false_positives_for_existing_categories 关键测试:确保存在的分类不会被误报为缺失 无分类误报
test_check_result_structure 测试结果结构正确性 返回结果符合预期结构
test_secondary_stats_accuracy 测试二级分类统计准确性 统计数据一致
test_category_code_consistency 测试分类代码一致性 检查大小写问题
test_chunks_with_invalid_categories 测试无效分类的处理 正确处理无效分类
test_completeness_accuracy_report 完整性审查准确性测试报告 输出详细统计信息

运行测试

运行所有测试

python -m pytest utils_test/Completeness_Test/test_completeness_accuracy.py -v

运行关键测试(误报检测)

python -m pytest utils_test/Completeness_Test/test_completeness_accuracy.py::TestCompletenessAccuracy::test_no_false_positives_for_existing_categories -v -s

查看详细报告

python -m pytest utils_test/Completeness_Test/test_completeness_accuracy.py::TestCompletenessAccuracy::test_completeness_accuracy_report -v -s

测试统计概览

基于测试数据,各章节的完整性统计如下:

章节 块数 存在分类 标准分类 缺失 完整率
basis 5 5 16 11 31.2%
overview 7 6 16 10 37.5%
plan 5 5 11 6 45.5%
technology 16 7 28 21 25.0%
safety 12 4 20 16 20.0%
quality 4 3 15 12 20.0%
environment 3 3 10 7 30.0%
management 4 0 0 0 0.0%
acceptance 5 5 24 19 20.8%
other 4 2 21 19 9.5%

测试逻辑与统计准确性说明

1. 核心测试原理(集合论验证)

测试基于集合交集原理验证统计准确性:

设:
- A = 实际存在的分类集合(从 chunks 提取)
- B = 检查器报告的缺失分类集合

若 A ∩ B = ∅(空集),则证明:
✓ 所有实际存在的分类都没有被误报为缺失
✓ 检查器的统计逻辑正确

为什么这种方法有效?

条件 数学表达 含义
无误报 A ∩ B = ∅ 实际存在的分类与报告缺失的分类无交集
有遗漏 B - A ≠ ∅ 报告缺失的分类中,部分是真正缺失的
完全正确 A ∪ B = 标准集 实际存在 + 真正缺失 = 标准分类全集

2. 误报检测逻辑(核心测试代码)

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"]
    }

    # 步骤3:计算交集(潜在的误报)
    false_positives = reported_missing & actual_tertiary

    # 步骤4:验证无交集(核心断言)
    assert len(false_positives) == 0, f"存在 {len(false_positives)} 个误报: {false_positives}"

3. 数据流验证流程

┌─────────────────────────────────────────────────────────────────────────┐
│                          测试数据准备阶段                                 │
├─────────────────────────────────────────────────────────────────────────┤
│  测试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                                  │
│     ↓                                                                    │
│  若通过:✓ 检查器统计正确,无误报                                         │
│  若失败:✗ 列出误报项,测试失败                                           │
└─────────────────────────────────────────────────────────────────────────┘

4. 分类提取逻辑

# 从 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个测试用例,覆盖所有关键场景
  • 结论: 完整性审查模块工作正常,没有出现"分类结果中存在但被误报为缺失"的情况

测试执行示例(关键测试)

$ 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

测试执行示例(详细报告)

$ 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文件
  2. 标准CSV依赖: 测试依赖于 core/construction_review/component/doc_worker/config/StandardCategoryTable.csv
  3. 分类代码匹配: 确保 chunk 中的分类代码与标准CSV中的代码大小写一致