| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- """
- 标准库匹配规则单元测试
- 通过 conftest.py 加载生产代码 standard_service.py(绕过 package __init__.py 重依赖)
- """
- import sys
- import os
- import pytest
- # 使用 conftest.py 中的共享 fixtures 和工厂函数
- from conftest import (
- StandardRepository, StandardMatcher, MatchResultCode,
- create_matcher, DEFAULT_MOCK_DATA,
- )
- class TestStandardRepository:
- """测试数据仓库"""
- def test_load_data(self, repository):
- """测试数据加载"""
- assert len(repository.get_all_records()) == 8
- def test_find_by_number_exact(self, repository):
- """测试精确匹配标准号"""
- result = repository.find_by_number_exact("TB 10002-2017")
- assert result is not None
- assert result.standard_name == "铁路桥涵设计规范"
- def test_find_by_name_exact(self, repository):
- """测试精确匹配名称"""
- result = repository.find_by_name_exact("铁路桥涵设计规范")
- assert result is not None
- assert result.standard_number == "TB 10002-2017"
- def test_find_current_by_name(self, repository):
- """测试查询现行标准(使用规范化名称)"""
- # 生产代码的 find_current_by_normalized_name 使用归一化名称
- # 注意:归一化保留了中文顿号"、"
- normalized = repository._normalize_for_matching("起重机 钢丝绳 保养、维护、检验和报废")
- results = repository.find_current_by_normalized_name(normalized)
- assert len(results) == 1
- assert results[0].standard_number == "GB/T 5972-2023"
- class TestStandardMatcher:
- """测试匹配器(基于生产代码的归一化匹配逻辑)"""
- def test_case1_ok(self, matcher):
- """情况1: 状态正常"""
- result = matcher.match(1, "铁路桥涵设计规范", "TB 10002-2017")
- assert result.status_code == MatchResultCode.OK.value
- assert result.final_result == "无问题"
- def test_case2_substituted(self, matcher):
- """情况2: 被替代"""
- result = matcher.match(1, "起重机 钢丝绳 保养、维护、检验和报废", "GB/T 5972-2016")
- assert result.status_code == MatchResultCode.SUBSTITUTED.value
- assert result.substitute_number == "(GB/T 5972-2023)"
- assert "已废止" in result.final_result
- def test_case3_abolished(self, matcher):
- """情况3: 废止无替代"""
- result = matcher.match(1, "缆索起重机", "GB/T 28756-2012")
- assert result.status_code == MatchResultCode.ABOLISHED.value
- assert "无现行状态" in result.final_result
- def test_case4_mismatch(self, matcher):
- """情况4: 不匹配"""
- result = matcher.match(1, "公路水运危险性较大工程专项施工方案编制审查规程", "JT/T 1495-2023")
- assert result.status_code == MatchResultCode.MISMATCH.value
- assert result.substitute_number == "(JT/T 1495-2024)"
- def test_case5_not_found(self, matcher):
- """情况5: 不存在"""
- result = matcher.match(1, "不存在的标准", "GB/T 99999-9999")
- assert result.status_code == MatchResultCode.NOT_FOUND.value
- def test_empty_name_returns_none(self, matcher):
- """空名称应返回 None(生产代码跳过审查逻辑)"""
- result = matcher.match(1, "", "TB 10002-2017")
- assert result is None
- def test_raw_fields_preserved(self, matcher):
- """验证原始输入字段正确保存"""
- result = matcher.match(1, "《铁路桥涵设计规范》", "(TB 10002-2017)")
- assert result is not None
- assert result.raw_name == "《铁路桥涵设计规范》"
- assert result.raw_number == "(TB 10002-2017)"
- assert result.normalized_name == "铁路桥涵设计规范"
- assert result.normalized_number == "TB100022017"
- assert result.status_code == MatchResultCode.OK.value
- class TestStandardMatchingBatch:
- """测试批量检查(模拟 StandardMatchingService.check_standards 逻辑)"""
- def test_check_standards_batch(self, matcher):
- """测试批量检查"""
- standards = [
- {"standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017"},
- {"standard_name": "缆索起重机", "standard_number": "GB/T 28756-2012"},
- {"standard_name": "不存在的标准", "standard_number": "GB/T 99999-9999"},
- ]
- from conftest import check_standards_via_matcher
- results = check_standards_via_matcher(matcher, standards)
- assert len(results) == 3
- assert results[0].status_code == MatchResultCode.OK.value
- assert results[1].status_code == MatchResultCode.ABOLISHED.value
- assert results[2].status_code == MatchResultCode.NOT_FOUND.value
- def test_batch_filters_none(self, matcher):
- """空名称应被过滤(生产代码行为)"""
- standards = [
- {"standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017"},
- {"standard_name": "", "standard_number": "TB 10002-2017"}, # 空名称
- ]
- from conftest import check_standards_via_matcher
- results = check_standards_via_matcher(matcher, standards)
- assert len(results) == 1
- assert results[0].status_code == MatchResultCode.OK.value
- class TestDocumentExamples:
- """测试文档中列出的7个示例"""
- def test_example_1_railway_bridge(self, matcher):
- """(1)《铁路桥涵设计规范》(TB 10002-2017) - 正常"""
- result = matcher.match(1, "铁路桥涵设计规范", "TB 10002-2017")
- assert result.status_code == MatchResultCode.OK.value
- def test_example_2_seismic_design(self, matcher):
- """(2)《铁路工程抗震设计规范》(GB 50111-2006) - 正常"""
- result = matcher.match(1, "铁路工程抗震设计规范", "GB 50111-2006")
- assert result.status_code == MatchResultCode.OK.value
- def test_example_3_concrete(self, matcher):
- """(3)《铁路混凝土工程施工质量验收标准》(TB 10424-2018) - 正常"""
- result = matcher.match(1, "铁路混凝土工程施工质量验收标准", "TB 10424-2018")
- assert result.status_code == MatchResultCode.OK.value
- def test_example_4_highway_mismatch(self, matcher):
- """(4)年份不匹配 - 应为2024"""
- result = matcher.match(1, "公路水运危险性较大工程专项施工方案编制审查规程", "JT/T 1495-2023")
- assert result.status_code == MatchResultCode.MISMATCH.value
- assert result.substitute_number == "(JT/T 1495-2024)"
- def test_example_5_crane_wire_substituted(self, matcher):
- """(5)被替代 GB/T 5972-2016 -> GB/T 5972-2023"""
- result = matcher.match(1, "起重机 钢丝绳 保养、维护、检验和报废", "GB/T 5972-2016")
- assert result.status_code == MatchResultCode.SUBSTITUTED.value
- assert result.substitute_number == "(GB/T 5972-2023)"
- def test_example_6_cable_crane_abolished(self, matcher):
- """(6)废止无替代"""
- result = matcher.match(1, "缆索起重机", "GB/T 28756-2012")
- assert result.status_code == MatchResultCode.ABOLISHED.value
- def test_example_7_safety_device_abolished(self, matcher):
- """(7)废止无替代"""
- result = matcher.match(1, "电力高处作业防坠器", "DL/T 1147-2009")
- assert result.status_code == MatchResultCode.ABOLISHED.value
- if __name__ == "__main__":
- pytest.main([__file__, "-v"])
|