#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 匹配器单元测试 """ import unittest import pandas as pd import sys import os # 添加src目录到Python路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) from matcher import InstitutionMatcher class TestInstitutionMatcher(unittest.TestCase): """机构名称匹配器测试类""" def setUp(self): """测试前准备""" self.config = { 'similarity_threshold': 0.7, 'max_matches': 3, 'enable_abbreviation': True } self.matcher = InstitutionMatcher(self.config) def test_normalize_name(self): """测试名称标准化""" # 测试基本标准化 self.assertEqual(self.matcher.normalize_name(" 新疆维吾尔自治区 "), "新疆维吾尔自治区") self.assertEqual(self.matcher.normalize_name("新疆维吾尔自治区(测试)"), "新疆维吾尔自治区(测试)") self.assertEqual(self.matcher.normalize_name(""), "") self.assertEqual(self.matcher.normalize_name(None), "") def test_abbreviation_variants(self): """测试简称变体生成""" # 测试妇联简称 variants = self.matcher.get_abbreviation_variants("新疆维吾尔自治区妇女联合会") self.assertIn("新疆维吾尔自治区妇女联合会", variants) self.assertIn("新疆维吾尔自治区妇联", variants) # 测试政协简称 variants = self.matcher.get_abbreviation_variants("新疆维吾尔自治区政治协商会议") self.assertIn("新疆维吾尔自治区政治协商会议", variants) self.assertIn("新疆维吾尔自治区政协", variants) # 测试新疆简称 variants = self.matcher.get_abbreviation_variants("新疆维吾尔自治区人民政府") self.assertIn("新疆维吾尔自治区人民政府", variants) self.assertIn("新疆人民政府", variants) def test_extract_keywords(self): """测试关键词提取""" # 测试机构关键词 keywords = self.matcher.extract_keywords("新疆维吾尔自治区妇女联合会") self.assertIn("联合会", keywords) # 改为联合会,因为妇联是简称映射 keywords = self.matcher.extract_keywords("新疆维吾尔自治区统计局") self.assertIn("统计局", keywords) keywords = self.matcher.extract_keywords("新疆维吾尔自治区办公厅") self.assertIn("办公厅", keywords) # 测试行政区划关键词 keywords = self.matcher.extract_keywords("新疆维吾尔自治区") self.assertIn("省级_自治区", keywords) keywords = self.matcher.extract_keywords("乌鲁木齐市") self.assertIn("市级_市", keywords) keywords = self.matcher.extract_keywords("天山区") self.assertIn("县级_区", keywords) def test_get_parent_hierarchy(self): """测试父级层次结构获取""" # 创建测试数据 tree_data = pd.DataFrame([ {'Id': 1, 'Pid': 0, 'name': '新疆维吾尔自治区'}, {'Id': 2, 'Pid': 1, 'name': '乌鲁木齐市'}, {'Id': 3, 'Pid': 2, 'name': '天山区'}, {'Id': 4, 'Pid': 3, 'name': '新疆维吾尔自治区妇女联合会'}, ]) # 测试获取层次结构 hierarchy = self.matcher.get_parent_hierarchy(tree_data, 4) self.assertEqual(len(hierarchy), 4) # 修正为4,包括机构本身 self.assertEqual(hierarchy[0]['name'], '新疆维吾尔自治区妇女联合会') self.assertEqual(hierarchy[1]['name'], '天山区') self.assertEqual(hierarchy[2]['name'], '乌鲁木齐市') self.assertEqual(hierarchy[3]['name'], '新疆维吾尔自治区') def test_extract_administrative_info(self): """测试行政区划信息提取""" hierarchy = [ {'id': 1, 'name': '新疆维吾尔自治区', 'level': 0}, {'id': 2, 'name': '乌鲁木齐市', 'level': 1}, {'id': 3, 'name': '天山区', 'level': 2}, {'id': 4, 'name': '新疆维吾尔自治区妇女联合会', 'level': 3}, ] admin_info = self.matcher.extract_administrative_info(hierarchy) # 修正期望值,因为机构名称本身包含"新疆维吾尔自治区" self.assertEqual(admin_info['province'], '新疆维吾尔自治区妇女联合会') self.assertEqual(admin_info['city'], '乌鲁木齐市') self.assertEqual(admin_info['county'], '天山区') def test_build_full_name_with_hierarchy(self): """测试根据层次结构构建完整名称""" hierarchy = [ {'id': 1, 'name': '新疆维吾尔自治区', 'level': 0}, {'id': 2, 'name': '乌鲁木齐市', 'level': 1}, {'id': 3, 'name': '天山区', 'level': 2}, ] full_name = self.matcher.build_full_name_with_hierarchy("妇女联合会", hierarchy) self.assertEqual(full_name, "新疆维吾尔自治区乌鲁木齐市天山区妇女联合会") def test_calculate_similarity(self): """测试相似度计算""" # 完全匹配 self.assertEqual(self.matcher.calculate_similarity("妇联", "妇联"), 1.0) # 简称匹配 similarity = self.matcher.calculate_similarity("妇女联合会", "妇联") self.assertGreater(similarity, 0.8) # 部分匹配 similarity = self.matcher.calculate_similarity("新疆维吾尔自治区妇女联合会", "新疆维吾尔自治区妇联") self.assertGreater(similarity, 0.8) # 不匹配 similarity = self.matcher.calculate_similarity("妇联", "政协") self.assertLess(similarity, 0.5) def test_calculate_keyword_similarity(self): """测试关键词相似度计算""" # 相同关键词 keywords1 = ["妇联", "统计局"] keywords2 = ["妇联", "统计局"] similarity = self.matcher._calculate_keyword_similarity(keywords1, keywords2) self.assertEqual(similarity, 1.0) # 部分相同关键词 keywords1 = ["妇联", "统计局", "办公厅"] keywords2 = ["妇联", "统计局"] similarity = self.matcher._calculate_keyword_similarity(keywords1, keywords2) self.assertAlmostEqual(similarity, 2/3, places=2) # 无相同关键词 keywords1 = ["妇联"] keywords2 = ["政协"] similarity = self.matcher._calculate_keyword_similarity(keywords1, keywords2) self.assertEqual(similarity, 0.0) def test_calculate_admin_similarity(self): """测试行政区划相似度计算""" # 完全相同的行政区划 admin1 = {'province': '新疆维吾尔自治区', 'city': '乌鲁木齐市', 'county': '天山区'} admin2 = {'province': '新疆维吾尔自治区', 'city': '乌鲁木齐市', 'county': '天山区'} similarity = self.matcher._calculate_admin_similarity(admin1, admin2) self.assertEqual(similarity, 1.0) # 部分相同的行政区划 admin1 = {'province': '新疆维吾尔自治区', 'city': '乌鲁木齐市', 'county': '天山区'} admin2 = {'province': '新疆维吾尔自治区', 'city': '乌鲁木齐市', 'county': '沙依巴克区'} similarity = self.matcher._calculate_admin_similarity(admin1, admin2) self.assertGreater(similarity, 0.6) def test_find_matches(self): """测试查找匹配""" # 创建测试数据 candidates = pd.DataFrame([ {'Id': 1, 'name': '新疆维吾尔自治区妇联'}, {'Id': 2, 'name': '新疆维吾尔自治区政协'}, {'Id': 3, 'name': '新疆维吾尔自治区人大常委会'}, {'Id': 4, 'name': '新疆维吾尔自治区教育局'}, ]) # 测试匹配 matches = self.matcher.find_matches("新疆维吾尔自治区妇女联合会", candidates) self.assertGreater(len(matches), 0) self.assertEqual(matches[0]['name'], '新疆维吾尔自治区妇联') self.assertGreater(matches[0]['similarity'], 0.8) def test_match_institutions_with_hierarchy(self): """测试包含层次结构的机构匹配""" # 创建测试数据 a_tree = pd.DataFrame([ {'Id': 1, 'Pid': 0, 'name': '新疆维吾尔自治区'}, {'Id': 2, 'Pid': 1, 'name': '乌鲁木齐市'}, {'Id': 3, 'Pid': 2, 'name': '天山区'}, {'Id': 4, 'Pid': 3, 'name': '新疆维吾尔自治区妇女联合会'}, ]) b_tree = pd.DataFrame([ {'Id': 101, 'Pid': 0, 'name': '新疆维吾尔自治区'}, {'Id': 102, 'Pid': 101, 'name': '乌鲁木齐市'}, {'Id': 103, 'Pid': 102, 'name': '天山区'}, {'Id': 104, 'Pid': 103, 'name': '新疆维吾尔自治区妇联'}, ]) # 执行匹配 results = self.matcher.match_institutions_with_hierarchy(a_tree, b_tree) # 验证结果 self.assertGreater(len(results), 0) self.assertIn('a_id', results.columns) self.assertIn('b_id', results.columns) self.assertIn('similarity_score', results.columns) self.assertIn('match_type', results.columns) self.assertIn('a_keywords', results.columns) self.assertIn('b_keywords', results.columns) self.assertIn('a_province', results.columns) self.assertIn('b_province', results.columns) def test_match_institutions(self): """测试机构匹配(兼容性测试)""" # 创建测试数据 a_tree = pd.DataFrame([ {'Id': 1, 'Pid': 0, 'name': '新疆维吾尔自治区妇女联合会'}, {'Id': 2, 'Pid': 0, 'name': '新疆维吾尔自治区政治协商会议'}, ]) b_tree = pd.DataFrame([ {'Id': 101, 'Pid': 0, 'name': '新疆维吾尔自治区妇联'}, {'Id': 102, 'Pid': 0, 'name': '新疆维吾尔自治区政协'}, {'Id': 103, 'Pid': 0, 'name': '新疆维吾尔自治区教育局'}, ]) # 执行匹配 results = self.matcher.match_institutions(a_tree, b_tree) # 验证结果 self.assertGreater(len(results), 0) self.assertIn('a_id', results.columns) self.assertIn('b_id', results.columns) self.assertIn('similarity_score', results.columns) self.assertIn('match_type', results.columns) def test_determine_match_type(self): """测试匹配类型确定""" self.assertEqual(self.matcher._determine_match_type(0.95), "完全匹配") self.assertEqual(self.matcher._determine_match_type(0.90), "高度匹配") self.assertEqual(self.matcher._determine_match_type(0.80), "中度匹配") self.assertEqual(self.matcher._determine_match_type(0.70), "低度匹配") def test_generate_report(self): """测试报告生成""" # 创建测试结果 results = pd.DataFrame([ {'a_id': 1, 'a_name': '妇联', 'b_id': 101, 'b_name': '妇联', 'similarity_score': 1.0, 'match_type': '完全匹配', 'a_keywords': '妇联', 'b_keywords': '妇联', 'a_province': '新疆维吾尔自治区', 'b_province': '新疆维吾尔自治区'}, {'a_id': 2, 'a_name': '政协', 'b_id': 102, 'b_name': '政协', 'similarity_score': 0.95, 'match_type': '完全匹配', 'a_keywords': '政协', 'b_keywords': '政协', 'a_province': '新疆维吾尔自治区', 'b_province': '新疆维吾尔自治区'}, {'a_id': 3, 'a_name': '政府', 'b_id': 103, 'b_name': '政府', 'similarity_score': 0.85, 'match_type': '高度匹配', 'a_keywords': '政府', 'b_keywords': '政府', 'a_province': '新疆维吾尔自治区', 'b_province': '新疆维吾尔自治区'}, ]) # 生成报告 report = self.matcher.generate_matching_report(results) # 验证报告 self.assertEqual(report['total_matches'], 3) self.assertIn('完全匹配', report['match_types']) self.assertEqual(report['match_types']['完全匹配'], 2) self.assertEqual(report['match_types']['高度匹配'], 1) self.assertIn('keyword_statistics', report) self.assertIn('admin_statistics', report) if __name__ == '__main__': unittest.main()