test_standard_matching.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. """
  2. 标准库匹配规则单元测试 - 内存处理版本
  3. 测试文档中定义的5种匹配情况
  4. """
  5. import sys
  6. import os
  7. # 添加项目根目录到 Python 路径
  8. current_dir = os.path.dirname(os.path.abspath(__file__))
  9. project_root = os.path.dirname(os.path.dirname(current_dir))
  10. if project_root not in sys.path:
  11. sys.path.insert(0, project_root)
  12. import pytest
  13. import asyncio
  14. from utils_test.standard_new_Test.standard_service import (
  15. StandardRepository,
  16. StandardMatcher,
  17. StandardMatchingService,
  18. MatchResultCode,
  19. ValidityStatus,
  20. StandardRecord
  21. )
  22. @pytest.fixture
  23. def mock_repository():
  24. """创建模拟的数据仓库"""
  25. repo = StandardRepository()
  26. mock_data = [
  27. # 情况1: 正常现行标准
  28. {"id": 1, "standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017", "validity": "XH"},
  29. {"id": 2, "standard_name": "铁路工程抗震设计规范", "standard_number": "GB 50111-2006", "validity": "XH"},
  30. {"id": 3, "standard_name": "铁路混凝土工程施工质量验收标准", "standard_number": "TB 10424-2018", "validity": "XH"},
  31. # 情况4: 不匹配(年份错误)- 输入2023,实际2024
  32. {"id": 4, "standard_name": "公路水运危险性较大工程专项施工方案编制审查规程", "standard_number": "JT/T 1495-2024", "validity": "XH"},
  33. # 情况2: 被替代(废止+有现行替代)
  34. {"id": 5, "standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2016", "validity": "FZ"},
  35. {"id": 6, "standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2023", "validity": "XH"},
  36. # 情况3: 废止无替代
  37. {"id": 7, "standard_name": "缆索起重机", "standard_number": "GB/T 28756-2012", "validity": "FZ"},
  38. {"id": 8, "standard_name": "电力高处作业防坠器", "standard_number": "DL/T 1147-2009", "validity": "FZ"},
  39. ]
  40. repo.load_data(mock_data)
  41. return repo
  42. @pytest.fixture
  43. def matcher(mock_repository):
  44. """创建匹配器实例"""
  45. return StandardMatcher(mock_repository)
  46. @pytest.fixture
  47. def mock_service():
  48. """创建使用Mock数据的服务"""
  49. service = StandardMatchingService(db_pool=None)
  50. # 同步初始化(测试时使用event loop)
  51. loop = asyncio.get_event_loop()
  52. loop.run_until_complete(service.initialize())
  53. return service
  54. class TestStandardRepository:
  55. """测试数据仓库"""
  56. def test_load_data(self, mock_repository):
  57. """测试数据加载"""
  58. assert len(mock_repository.get_all_records()) == 8
  59. def test_find_by_number_exact(self, mock_repository):
  60. """测试精确匹配标准号"""
  61. result = mock_repository.find_by_number_exact("TB 10002-2017")
  62. assert result is not None
  63. assert result.standard_name == "铁路桥涵设计规范"
  64. def test_find_by_name_exact(self, mock_repository):
  65. """测试精确匹配名称"""
  66. result = mock_repository.find_by_name_exact("铁路桥涵设计规范")
  67. assert result is not None
  68. assert result.standard_number == "TB 10002-2017"
  69. def test_find_current_by_name(self, mock_repository):
  70. """测试查询现行标准"""
  71. results = mock_repository.find_current_by_name("起重机 钢丝绳 保养、维护、检验和报废")
  72. assert len(results) == 1
  73. assert results[0].standard_number == "GB/T 5972-2023"
  74. class TestStandardMatcher:
  75. """测试匹配器"""
  76. def test_case1_ok(self, matcher):
  77. """情况1: 状态正常"""
  78. result = matcher.match(1, "铁路桥涵设计规范", "TB 10002-2017")
  79. assert result.status_code == MatchResultCode.OK.value
  80. assert result.final_result == "无问题"
  81. def test_case2_substituted(self, matcher):
  82. """情况2: 被替代"""
  83. result = matcher.match(1, "起重机 钢丝绳 保养、维护、检验和报废", "GB/T 5972-2016")
  84. assert result.status_code == MatchResultCode.SUBSTITUTED.value
  85. assert result.substitute_number == "GB/T 5972-2023"
  86. assert "已废止" in result.final_result
  87. def test_case3_abolished(self, matcher):
  88. """情况3: 废止无替代"""
  89. result = matcher.match(1, "缆索起重机", "GB/T 28756-2012")
  90. assert result.status_code == MatchResultCode.ABOLISHED.value
  91. assert "无现行状态" in result.final_result
  92. def test_case4_mismatch(self, matcher):
  93. """情况4: 不匹配"""
  94. result = matcher.match(1, "公路水运危险性较大工程专项施工方案编制审查规程", "JT/T 1495-2023")
  95. assert result.status_code == MatchResultCode.MISMATCH.value
  96. assert result.substitute_number == "JT/T 1495-2024"
  97. def test_case5_not_found(self, matcher):
  98. """情况5: 不存在"""
  99. result = matcher.match(1, "不存在的标准", "GB/T 99999-9999")
  100. assert result.status_code == MatchResultCode.NOT_FOUND.value
  101. class TestStandardMatchingService:
  102. """测试服务类"""
  103. def test_check_single(self, mock_service):
  104. """测试单个检查"""
  105. result = mock_service.check_single(1, "铁路桥涵设计规范", "TB 10002-2017")
  106. assert result.status_code == MatchResultCode.OK.value
  107. def test_check_standards_batch(self, mock_service):
  108. """测试批量检查"""
  109. standards = [
  110. {"standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017"},
  111. {"standard_name": "缆索起重机", "standard_number": "GB/T 28756-2012"},
  112. {"standard_name": "不存在的标准", "standard_number": "GB/T 99999-9999"},
  113. ]
  114. results = mock_service.check_standards(standards)
  115. assert len(results) == 3
  116. assert results[0].status_code == MatchResultCode.OK.value
  117. assert results[1].status_code == MatchResultCode.ABOLISHED.value
  118. assert results[2].status_code == MatchResultCode.NOT_FOUND.value
  119. class TestDocumentExamples:
  120. """测试文档中列出的7个示例"""
  121. @pytest.fixture
  122. def doc_matcher(self):
  123. """文档测试专用匹配器"""
  124. repo = StandardRepository()
  125. mock_data = [
  126. {"id": 1, "standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017", "validity": "XH"},
  127. {"id": 2, "standard_name": "铁路工程抗震设计规范", "standard_number": "GB 50111-2006", "validity": "XH"},
  128. {"id": 3, "standard_name": "铁路混凝土工程施工质量验收标准", "standard_number": "TB 10424-2018", "validity": "XH"},
  129. {"id": 4, "standard_name": "公路水运危险性较大工程专项施工方案编制审查规程", "standard_number": "JT/T 1495-2024", "validity": "XH"},
  130. {"id": 5, "standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2016", "validity": "FZ"},
  131. {"id": 6, "standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2023", "validity": "XH"},
  132. {"id": 7, "standard_name": "缆索起重机", "standard_number": "GB/T 28756-2012", "validity": "FZ"},
  133. {"id": 8, "standard_name": "电力高处作业防坠器", "standard_number": "DL/T 1147-2009", "validity": "FZ"},
  134. ]
  135. repo.load_data(mock_data)
  136. return StandardMatcher(repo)
  137. def test_example_1_railway_bridge(self, doc_matcher):
  138. """(1)《铁路桥涵设计规范》(TB 10002-2017) - 正常"""
  139. result = doc_matcher.match(1, "铁路桥涵设计规范", "TB 10002-2017")
  140. assert result.status_code == MatchResultCode.OK.value
  141. def test_example_2_seismic_design(self, doc_matcher):
  142. """(2)《铁路工程抗震设计规范》(GB 50111-2006) - 正常"""
  143. result = doc_matcher.match(1, "铁路工程抗震设计规范", "GB 50111-2006")
  144. assert result.status_code == MatchResultCode.OK.value
  145. def test_example_3_concrete(self, doc_matcher):
  146. """(3)《铁路混凝土工程施工质量验收标准》(TB 10424-2018) - 正常"""
  147. result = doc_matcher.match(1, "铁路混凝土工程施工质量验收标准", "TB 10424-2018")
  148. assert result.status_code == MatchResultCode.OK.value
  149. def test_example_4_highway_mismatch(self, doc_matcher):
  150. """(4)年份不匹配 - 应为2024"""
  151. result = doc_matcher.match(1, "公路水运危险性较大工程专项施工方案编制审查规程", "JT/T 1495-2023")
  152. assert result.status_code == MatchResultCode.MISMATCH.value
  153. assert result.substitute_number == "JT/T 1495-2024"
  154. def test_example_5_crane_wire_substituted(self, doc_matcher):
  155. """(5)被替代 GB/T 5972-2016 -> GB/T 5972-2023"""
  156. result = doc_matcher.match(1, "起重机 钢丝绳 保养、维护、检验和报废", "GB/T 5972-2016")
  157. assert result.status_code == MatchResultCode.SUBSTITUTED.value
  158. assert result.substitute_number == "GB/T 5972-2023"
  159. def test_example_6_cable_crane_abolished(self, doc_matcher):
  160. """(6)废止无替代"""
  161. result = doc_matcher.match(1, "缆索起重机", "GB/T 28756-2012")
  162. assert result.status_code == MatchResultCode.ABOLISHED.value
  163. def test_example_7_safety_device_abolished(self, doc_matcher):
  164. """(7)废止无替代"""
  165. result = doc_matcher.match(1, "电力高处作业防坠器", "DL/T 1147-2009")
  166. assert result.status_code == MatchResultCode.ABOLISHED.value
  167. if __name__ == "__main__":
  168. pytest.main([__file__, "-v"])