236 lines
7.1 KiB
Python
236 lines
7.1 KiB
Python
"""
|
||
测试RobustJSONParser的各种修复能力。
|
||
|
||
验证解析器能够处理:
|
||
1. 基本的markdown包裹
|
||
2. 思考内容清理
|
||
3. 缺少逗号的修复
|
||
4. 括号不平衡的修复
|
||
5. 控制字符转义
|
||
6. 尾随逗号移除
|
||
"""
|
||
|
||
import json
|
||
import unittest
|
||
from json_parser import RobustJSONParser, JSONParseError
|
||
|
||
|
||
class TestRobustJSONParser(unittest.TestCase):
|
||
"""测试鲁棒JSON解析器的各种修复策略。"""
|
||
|
||
def setUp(self):
|
||
"""初始化解析器。"""
|
||
self.parser = RobustJSONParser(
|
||
enable_json_repair=False, # 先测试本地修复
|
||
enable_llm_repair=False,
|
||
)
|
||
|
||
def test_basic_json(self):
|
||
"""测试解析基本的合法JSON。"""
|
||
json_str = '{"name": "test", "value": 123}'
|
||
result = self.parser.parse(json_str, "基本测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["value"], 123)
|
||
|
||
def test_markdown_wrapped(self):
|
||
"""测试解析被```json包裹的JSON。"""
|
||
json_str = """```json
|
||
{
|
||
"name": "test",
|
||
"value": 123
|
||
}
|
||
```"""
|
||
result = self.parser.parse(json_str, "Markdown包裹测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["value"], 123)
|
||
|
||
def test_thinking_content_removal(self):
|
||
"""测试清理思考内容。"""
|
||
json_str = """<thinking>让我想想如何构造这个JSON</thinking>
|
||
{
|
||
"name": "test",
|
||
"value": 123
|
||
}"""
|
||
result = self.parser.parse(json_str, "思考内容清理测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["value"], 123)
|
||
|
||
def test_missing_comma_fix(self):
|
||
"""测试修复缺少的逗号。"""
|
||
# 这是实际错误中常见的情况:数组元素之间缺少逗号
|
||
json_str = """{
|
||
"totalWords": 40000,
|
||
"globalGuidelines": [
|
||
"重点突出技术红利分配失衡"
|
||
"详略策略:技术创新"
|
||
],
|
||
"chapters": []
|
||
}"""
|
||
result = self.parser.parse(json_str, "缺少逗号修复测试")
|
||
self.assertEqual(len(result["globalGuidelines"]), 2)
|
||
|
||
def test_unbalanced_brackets(self):
|
||
"""测试修复括号不平衡。"""
|
||
# 缺少结束括号
|
||
json_str = """{
|
||
"name": "test",
|
||
"nested": {
|
||
"value": 123
|
||
}
|
||
""" # 缺少最外层的 }
|
||
result = self.parser.parse(json_str, "括号不平衡测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["nested"]["value"], 123)
|
||
|
||
def test_control_character_escape(self):
|
||
"""测试转义控制字符。"""
|
||
# JSON字符串中的裸换行符应该被转义
|
||
json_str = """{
|
||
"text": "这是第一行
|
||
这是第二行",
|
||
"value": 123
|
||
}"""
|
||
result = self.parser.parse(json_str, "控制字符转义测试")
|
||
# 确保换行符被正确处理
|
||
self.assertIn("第一行", result["text"])
|
||
self.assertIn("第二行", result["text"])
|
||
|
||
def test_trailing_comma_removal(self):
|
||
"""测试移除尾随逗号。"""
|
||
json_str = """{
|
||
"name": "test",
|
||
"value": 123,
|
||
"items": [1, 2, 3,],
|
||
}"""
|
||
result = self.parser.parse(json_str, "尾随逗号测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(len(result["items"]), 3)
|
||
|
||
def test_colon_equals_fix(self):
|
||
"""测试修复冒号等号错误。"""
|
||
json_str = """{
|
||
"name":= "test",
|
||
"value": 123
|
||
}"""
|
||
result = self.parser.parse(json_str, "冒号等号测试")
|
||
self.assertEqual(result["name"], "test")
|
||
|
||
def test_extract_first_json(self):
|
||
"""测试从文本中提取第一个JSON结构。"""
|
||
json_str = """这是一些说明文字,下面是JSON:
|
||
{
|
||
"name": "test",
|
||
"value": 123
|
||
}
|
||
后面还有一些其他文字"""
|
||
result = self.parser.parse(json_str, "提取JSON测试")
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["value"], 123)
|
||
|
||
def test_complex_real_world_case(self):
|
||
"""测试真实世界的复杂案例(类似实际错误)。"""
|
||
# 模拟实际错误:缺少逗号、有markdown包裹、有思考内容
|
||
json_str = """<thinking>我需要构造一个篇幅规划</thinking>
|
||
```json
|
||
{
|
||
"totalWords": 40000,
|
||
"tolerance": 2000,
|
||
"globalGuidelines": [
|
||
"重点突出技术红利分配失衡、人才流失与职业认同危机等结构性矛盾"
|
||
"详略策略:技术创新与传统技艺的碰撞"
|
||
"案例导向:优先引用真实数据和调研"
|
||
],
|
||
"chapters": [
|
||
{
|
||
"chapterId": "ch1",
|
||
"targetWords": 5000
|
||
}
|
||
]
|
||
}
|
||
```"""
|
||
result = self.parser.parse(json_str, "复杂真实案例测试")
|
||
self.assertEqual(result["totalWords"], 40000)
|
||
self.assertEqual(result["tolerance"], 2000)
|
||
self.assertEqual(len(result["globalGuidelines"]), 3)
|
||
self.assertEqual(len(result["chapters"]), 1)
|
||
|
||
def test_expected_keys_validation(self):
|
||
"""测试期望键的验证。"""
|
||
json_str = '{"name": "test"}'
|
||
# 不应该因为缺少键而失败,只是警告
|
||
result = self.parser.parse(
|
||
json_str, "键验证测试", expected_keys=["name", "value"]
|
||
)
|
||
self.assertIn("name", result)
|
||
|
||
def test_wrapper_key_extraction(self):
|
||
"""测试从包裹键中提取数据。"""
|
||
json_str = """{
|
||
"wrapper": {
|
||
"name": "test",
|
||
"value": 123
|
||
}
|
||
}"""
|
||
result = self.parser.parse(
|
||
json_str, "包裹键测试", extract_wrapper_key="wrapper"
|
||
)
|
||
self.assertEqual(result["name"], "test")
|
||
self.assertEqual(result["value"], 123)
|
||
|
||
def test_empty_input(self):
|
||
"""测试空输入。"""
|
||
with self.assertRaises(JSONParseError):
|
||
self.parser.parse("", "空输入测试")
|
||
|
||
def test_invalid_json_after_all_repairs(self):
|
||
"""测试所有修复策略都无法处理的情况。"""
|
||
# 这是一个严重损坏的JSON,无法修复
|
||
json_str = "{完全不是JSON格式的内容###"
|
||
with self.assertRaises(JSONParseError):
|
||
self.parser.parse(json_str, "无法修复测试")
|
||
|
||
|
||
def run_manual_test():
|
||
"""手动运行测试,打印详细信息。"""
|
||
print("=" * 60)
|
||
print("开始测试RobustJSONParser")
|
||
print("=" * 60)
|
||
|
||
parser = RobustJSONParser(enable_json_repair=False, enable_llm_repair=False)
|
||
|
||
# 测试实际错误案例
|
||
test_case = """```json
|
||
{
|
||
"totalWords": 40000,
|
||
"tolerance": 2000,
|
||
"globalGuidelines": [
|
||
"重点突出技术红利分配失衡、人才流失与职业认同危机等结构性矛盾"
|
||
"详略策略:技术创新与传统技艺的碰撞"
|
||
],
|
||
"chapters": []
|
||
}
|
||
```"""
|
||
|
||
print("\n测试案例:")
|
||
print(test_case)
|
||
print("\n" + "=" * 60)
|
||
|
||
try:
|
||
result = parser.parse(test_case, "手动测试")
|
||
print("\n✓ 解析成功!")
|
||
print("\n解析结果:")
|
||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||
except Exception as e:
|
||
print(f"\n✗ 解析失败: {e}")
|
||
|
||
print("\n" + "=" * 60)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
# 运行手动测试
|
||
run_manual_test()
|
||
|
||
# 运行单元测试
|
||
print("\n\n运行单元测试...")
|
||
unittest.main(verbosity=2)
|