You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 

281 lines
12 KiB

#!/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()