| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- from standards_service.service.matcher import StandardMatcher
- from .conftest import row, write_csv
- def test_exact_code_and_title_returns_perfect_match(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("GB 50330-2013 建筑边坡工程技术规范")
- assert candidates[0]["code"] == "GB 50330-2013"
- assert candidates[0]["match_score"] == 1.0
- assert candidates[0]["relation_text"] == "替代 GB 50330-2002"
- def test_full_width_dash_is_normalized(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("GB 50330—2013")
- assert candidates[0]["code"] == "GB 50330-2013"
- assert candidates[0]["match_score"] == 1.0
- def test_spaces_around_code_separators_are_normalized(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("GB / T 6441 - 1986")
- assert candidates[0]["code"] == "GB 6441-1986"
- assert candidates[0]["match_score"] == 0.93
- def test_two_digit_year_matches_four_digit_year(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("CJJ 69-95")
- assert candidates[0]["code"] == "CJJ 69-1995"
- assert candidates[0]["match_score"] == 0.98
- def test_standard_type_variant_is_returned_below_exact_score(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("GB/T 6441-1986")
- assert candidates[0]["code"] == "GB 6441-1986"
- assert candidates[0]["match_score"] == 0.93
- def test_code_without_year_returns_only_top_three_versions(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("GB 50330")
- assert [item["code"] for item in candidates] == [
- "GB 50330-2023",
- "GB 50330-2018",
- "GB 50330-2013",
- ]
- assert all(item["match_score"] == 0.9 for item in candidates)
- def test_exact_title_returns_only_top_three_versions(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("建筑边坡工程技术规范")
- assert len(candidates) == 3
- assert candidates[0]["code"] == "GB 50330-2023"
- assert all(item["match_score"] == 1.0 for item in candidates)
- def test_title_typo_can_be_recalled(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("绕结多孔砖和多孔砌块")
- assert candidates[0]["code"] == "GB/T 13544-2011"
- assert 0.88 <= candidates[0]["match_score"] < 1.0
- def test_one_character_code_typo_needs_title_support(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("TG/T 5440-2018 公路隧道加固技术规范")
- assert candidates[0]["code"] == "JTG/T 5440-2018"
- assert candidates[0]["match_score"] < 1.0
- def test_different_year_with_related_title_is_returned_for_agent_review(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("JTG D70/2-2014 公路隧道设计规范")
- assert candidates[0]["code"] == "JTG D70-2004"
- assert 0 < candidates[0]["match_score"] < 0.8
- def test_same_code_stem_different_year_and_exact_title_is_returned(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("钢筋焊接及验收规程JGJ 18-2022")
- assert candidates[0]["code"] == "JGJ 18-2012"
- assert candidates[0]["match_score"] == 0.91
- def test_exact_title_is_returned_even_when_query_code_is_unrelated(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("XYZ 999-2022 钢筋焊接及验收规程")
- assert candidates[0]["code"] == "JGJ 18-2012"
- assert candidates[0]["match_score"] == 0.7
- def test_short_generic_title_has_reduced_score(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("验收规程")
- assert candidates[0]["code"] == "JGJ 18-2012"
- assert 0.75 <= candidates[0]["match_score"] < 0.9
- def test_relation_text_is_not_searchable(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- candidates = matcher.search("OLD 100-2000")
- assert candidates == []
- def test_unknown_query_returns_empty_list(standards_csv):
- matcher = StandardMatcher.from_csv(standards_csv)
- assert matcher.search("本地规范库中不存在的规范") == []
- def test_gb18030_csv_is_supported(tmp_path, standard_rows):
- path = write_csv(tmp_path / "standards-gb18030.csv", standard_rows, encoding="gb18030")
- matcher = StandardMatcher.from_csv(path)
- assert matcher.search("混凝土结构设计规范")[0]["code"] == "GB 50010-2010"
- def test_record_without_title_is_still_searchable_by_code(tmp_path):
- path = write_csv(tmp_path / "code-only.csv", [row("GB 99999-2026", "")])
- matcher = StandardMatcher.from_csv(path)
- candidates = matcher.search("GB 99999-2026")
- assert candidates[0]["code"] == "GB 99999-2026"
- assert candidates[0]["title"] == ""
|