299 lines
10 KiB
Python
299 lines
10 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
测试修正后的多主键删除逻辑
|
||
基于identityId列表长度而不是schema结构
|
||
"""
|
||
|
||
import sys
|
||
import json
|
||
from unittest.mock import Mock
|
||
from custom_stages.dms_crud_scenario_stage import DmsCrudScenarioStage
|
||
from ddms_compliance_suite.input_parser.parser import DMSEndpoint
|
||
|
||
def test_single_key_by_identity_id():
|
||
"""测试单主键删除(基于identityId长度=1)"""
|
||
|
||
print("🧪 测试单主键删除(identityId长度=1)")
|
||
print("=" * 60)
|
||
|
||
# 创建模拟的删除端点,identityId只有一个元素
|
||
mock_delete_endpoint = Mock(spec=DMSEndpoint)
|
||
mock_delete_endpoint.identity_id_list = ["proppantId"] # 单主键
|
||
|
||
# 创建模拟的scenario
|
||
scenario = {"delete": mock_delete_endpoint}
|
||
|
||
# 创建CRUD Stage实例
|
||
crud_stage = DmsCrudScenarioStage(
|
||
api_group_metadata={"name": "测试"},
|
||
apis_in_group=[],
|
||
global_api_spec=Mock()
|
||
)
|
||
|
||
# 测试构建删除请求体
|
||
create_payload = {"proppantId": "proppant_001", "proppantName": "测试支撑剂"}
|
||
delete_body = crud_stage._build_delete_request_body(
|
||
scenario, "proppantId", "proppant_001", create_payload
|
||
)
|
||
|
||
print(f"单主键删除请求体: {json.dumps(delete_body, indent=2, ensure_ascii=False)}")
|
||
|
||
# 验证结果:应该是字符串数组格式
|
||
expected_structure = {"data": ["proppant_001"]}
|
||
|
||
if delete_body == expected_structure:
|
||
print("✅ 单主键删除请求体格式正确(字符串数组)")
|
||
return True
|
||
else:
|
||
print(f"❌ 单主键删除请求体格式错误,期望: {expected_structure}")
|
||
return False
|
||
|
||
def test_multi_key_by_identity_id():
|
||
"""测试多主键删除(基于identityId长度>1)"""
|
||
|
||
print("\n🧪 测试多主键删除(identityId长度>1)")
|
||
print("=" * 60)
|
||
|
||
# 创建模拟的删除端点,identityId有多个元素
|
||
mock_delete_endpoint = Mock(spec=DMSEndpoint)
|
||
mock_delete_endpoint.identity_id_list = ["projectId", "surveyId"] # 多主键
|
||
|
||
# 创建模拟的scenario
|
||
scenario = {"delete": mock_delete_endpoint}
|
||
|
||
# 创建CRUD Stage实例
|
||
crud_stage = DmsCrudScenarioStage(
|
||
api_group_metadata={"name": "测试"},
|
||
apis_in_group=[],
|
||
global_api_spec=Mock()
|
||
)
|
||
|
||
# 测试构建删除请求体
|
||
create_payload = {
|
||
"projectId": "项目1_ID",
|
||
"surveyId": "工区1_ID",
|
||
"projectName": "测试项目",
|
||
"surveyName": "测试工区"
|
||
}
|
||
|
||
delete_body = crud_stage._build_delete_request_body(
|
||
scenario, "projectId", "项目1_ID", create_payload
|
||
)
|
||
|
||
print(f"多主键删除请求体: {json.dumps(delete_body, indent=2, ensure_ascii=False)}")
|
||
|
||
# 验证结果:应该是对象数组格式
|
||
if isinstance(delete_body, dict) and "data" in delete_body:
|
||
data_array = delete_body["data"]
|
||
|
||
if isinstance(data_array, list) and len(data_array) > 0:
|
||
first_item = data_array[0]
|
||
|
||
# 检查第一个对象是否包含正确的主键
|
||
if (isinstance(first_item, dict) and
|
||
first_item.get("projectId") == "项目1_ID" and
|
||
first_item.get("surveyId") == "工区1_ID"):
|
||
|
||
print("✅ 多主键删除请求体格式正确(对象数组)")
|
||
print(f"✅ 包含主键: projectId={first_item['projectId']}, surveyId={first_item['surveyId']}")
|
||
|
||
# 检查是否有版本号
|
||
if delete_body.get("version"):
|
||
print(f"✅ 包含版本号: {delete_body['version']}")
|
||
|
||
# 检查是否支持批量删除
|
||
if len(data_array) > 1:
|
||
print(f"✅ 支持批量删除,共{len(data_array)}个对象")
|
||
|
||
return True
|
||
else:
|
||
print(f"❌ 主键字段不正确: {first_item}")
|
||
return False
|
||
else:
|
||
print(f"❌ data数组格式错误: {data_array}")
|
||
return False
|
||
else:
|
||
print(f"❌ 删除请求体格式错误: {delete_body}")
|
||
return False
|
||
|
||
def test_three_key_scenario():
|
||
"""测试三主键删除场景"""
|
||
|
||
print("\n🧪 测试三主键删除场景")
|
||
print("=" * 60)
|
||
|
||
# 创建模拟的删除端点,identityId有三个元素
|
||
mock_delete_endpoint = Mock(spec=DMSEndpoint)
|
||
mock_delete_endpoint.identity_id_list = ["wellId", "layerId", "sampleId"] # 三主键
|
||
|
||
scenario = {"delete": mock_delete_endpoint}
|
||
|
||
crud_stage = DmsCrudScenarioStage(
|
||
api_group_metadata={"name": "测试"},
|
||
apis_in_group=[],
|
||
global_api_spec=Mock()
|
||
)
|
||
|
||
# 创建负载只包含部分主键
|
||
create_payload = {
|
||
"wellId": "井001",
|
||
"layerId": "层001",
|
||
# 注意:缺少sampleId
|
||
"wellName": "测试井",
|
||
"layerName": "测试层"
|
||
}
|
||
|
||
delete_body = crud_stage._build_delete_request_body(
|
||
scenario, "wellId", "井001", create_payload
|
||
)
|
||
|
||
print(f"三主键删除请求体: {json.dumps(delete_body, indent=2, ensure_ascii=False)}")
|
||
|
||
# 验证结果
|
||
if isinstance(delete_body, dict) and "data" in delete_body:
|
||
data_array = delete_body["data"]
|
||
if isinstance(data_array, list) and len(data_array) > 0:
|
||
first_item = data_array[0]
|
||
|
||
# 检查是否包含所有三个主键
|
||
required_keys = ["wellId", "layerId", "sampleId"]
|
||
missing_keys = [key for key in required_keys if key not in first_item]
|
||
|
||
if not missing_keys:
|
||
print("✅ 成功生成所有三个主键字段")
|
||
print(f"✅ wellId: {first_item['wellId']}")
|
||
print(f"✅ layerId: {first_item['layerId']}")
|
||
print(f"✅ sampleId: {first_item['sampleId']} (自动生成)")
|
||
return True
|
||
else:
|
||
print(f"❌ 缺失主键字段: {missing_keys}")
|
||
return False
|
||
else:
|
||
print(f"❌ data数组格式错误: {data_array}")
|
||
return False
|
||
else:
|
||
print(f"❌ 删除请求体格式错误: {delete_body}")
|
||
return False
|
||
|
||
def test_empty_identity_id_fallback():
|
||
"""测试identityId为空时的回退逻辑"""
|
||
|
||
print("\n🧪 测试identityId为空时的回退逻辑")
|
||
print("=" * 60)
|
||
|
||
# 创建模拟的删除端点,identityId为空
|
||
mock_delete_endpoint = Mock(spec=DMSEndpoint)
|
||
mock_delete_endpoint.identity_id_list = [] # 空列表
|
||
|
||
scenario = {"delete": mock_delete_endpoint}
|
||
|
||
crud_stage = DmsCrudScenarioStage(
|
||
api_group_metadata={"name": "测试"},
|
||
apis_in_group=[],
|
||
global_api_spec=Mock()
|
||
)
|
||
|
||
create_payload = {"siteId": "test_site_001"}
|
||
|
||
delete_body = crud_stage._build_delete_request_body(
|
||
scenario, "siteId", "test_site_001", create_payload
|
||
)
|
||
|
||
print(f"回退删除请求体: {json.dumps(delete_body, indent=2, ensure_ascii=False)}")
|
||
|
||
# 验证回退结果
|
||
expected_fallback = {"data": ["test_site_001"]}
|
||
|
||
if delete_body == expected_fallback:
|
||
print("✅ identityId为空时正确回退到简单格式")
|
||
return True
|
||
else:
|
||
print("❌ identityId为空时回退失败")
|
||
return False
|
||
|
||
def test_logic_comparison():
|
||
"""对比新旧逻辑的差异"""
|
||
|
||
print("\n🧪 对比新旧逻辑的差异")
|
||
print("=" * 60)
|
||
|
||
print("📋 新逻辑(基于identityId):")
|
||
print("- 单主键: identityId = ['proppantId'] → 字符串数组")
|
||
print("- 多主键: identityId = ['projectId', 'surveyId'] → 对象数组")
|
||
print("- 判断依据: len(identity_id_list)")
|
||
|
||
print("\n📋 旧逻辑(基于schema):")
|
||
print("- 单主键: items.type = 'string' → 字符串数组")
|
||
print("- 多主键: items.type = 'object' → 对象数组")
|
||
print("- 判断依据: schema结构分析")
|
||
|
||
print("\n✅ 新逻辑的优势:")
|
||
print("- 直接基于业务配置(identityId)")
|
||
print("- 不依赖schema解析")
|
||
print("- 更准确反映业务意图")
|
||
print("- 支持任意数量的主键组合")
|
||
|
||
return True
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("🚀 修正后的多主键删除逻辑测试")
|
||
print("=" * 80)
|
||
|
||
success_count = 0
|
||
total_tests = 5
|
||
|
||
# 测试1: 单主键删除
|
||
if test_single_key_by_identity_id():
|
||
success_count += 1
|
||
|
||
# 测试2: 多主键删除
|
||
if test_multi_key_by_identity_id():
|
||
success_count += 1
|
||
|
||
# 测试3: 三主键删除
|
||
if test_three_key_scenario():
|
||
success_count += 1
|
||
|
||
# 测试4: 空identityId回退
|
||
if test_empty_identity_id_fallback():
|
||
success_count += 1
|
||
|
||
# 测试5: 逻辑对比
|
||
if test_logic_comparison():
|
||
success_count += 1
|
||
|
||
# 总结
|
||
print("\n" + "=" * 80)
|
||
print("📋 测试总结")
|
||
print("=" * 80)
|
||
print(f"通过测试: {success_count}/{total_tests}")
|
||
|
||
if success_count == total_tests:
|
||
print("🎉 修正后的多主键删除逻辑测试通过!")
|
||
print("\n✅ 修正内容:")
|
||
print("1. 判断依据改为identityId列表长度")
|
||
print(" - len(identity_id_list) == 1 → 单主键(字符串数组)")
|
||
print(" - len(identity_id_list) > 1 → 多主键(对象数组)")
|
||
|
||
print("\n2. DMSEndpoint增加identity_id_list属性")
|
||
print(" - 存储完整的identityId配置")
|
||
print(" - 在解析DMS API时自动设置")
|
||
|
||
print("\n3. 删除schema自动生成")
|
||
print(" - 单主键: {\"data\": [\"key1\", \"key2\"]}")
|
||
print(" - 多主键: {\"version\": \"1.0.0\", \"data\": [{\"key1\": \"val1\", \"key2\": \"val2\"}]}")
|
||
|
||
print("\n💡 配置示例:")
|
||
print("单主键: \"identityId\": [\"proppantId\"]")
|
||
print("多主键: \"identityId\": [\"projectId\", \"surveyId\"]")
|
||
print("三主键: \"identityId\": [\"wellId\", \"layerId\", \"sampleId\"]")
|
||
|
||
sys.exit(0)
|
||
else:
|
||
print("❌ 部分测试失败")
|
||
sys.exit(1)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|