528 lines
17 KiB
Python
528 lines
17 KiB
Python
"""
|
||
MACP 基础测试模块。
|
||
|
||
对核心服务层进行单元测试,验证各模块基本功能正确性。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
from fastapi.testclient import TestClient
|
||
|
||
from app.main import app
|
||
from app.models import (
|
||
Document,
|
||
DocumentStatus,
|
||
FileType,
|
||
GjbRule,
|
||
GjbStandard,
|
||
KnowledgeChunk,
|
||
KnowledgeLevel,
|
||
McpTool,
|
||
MemoryEntry,
|
||
MemoryType,
|
||
Skill,
|
||
Template,
|
||
TemplateType,
|
||
Workflow,
|
||
)
|
||
from app.services import (
|
||
DocumentService,
|
||
GjbValidatorService,
|
||
KnowledgeBaseService,
|
||
McpToolService,
|
||
MemoryService,
|
||
ModelService,
|
||
MultimodalService,
|
||
SandboxService,
|
||
SkillService,
|
||
TemplateService,
|
||
)
|
||
|
||
|
||
# =============================================================================
|
||
# 客户端 Fixture
|
||
# =============================================================================
|
||
|
||
@pytest.fixture
|
||
def client():
|
||
"""FastAPI 测试客户端"""
|
||
with TestClient(app) as c:
|
||
yield c
|
||
|
||
|
||
# =============================================================================
|
||
# 健康检查测试
|
||
# =============================================================================
|
||
|
||
class TestHealthCheck:
|
||
"""健康检查接口测试"""
|
||
|
||
def test_health_endpoint(self, client):
|
||
"""测试 /api/health 接口"""
|
||
response = client.get("/api/health")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["status"] == "ok"
|
||
assert data["service"] == "MACP Platform"
|
||
|
||
def test_root_endpoint(self, client):
|
||
"""测试根路径"""
|
||
response = client.get("/")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert "MACP" in data["message"]
|
||
|
||
|
||
# =============================================================================
|
||
# 模板管理服务测试(SRS-MACP_F-001)
|
||
# =============================================================================
|
||
|
||
class TestTemplateService:
|
||
"""文档模板管理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = TemplateService()
|
||
|
||
def test_list_templates(self):
|
||
"""测试获取模板列表"""
|
||
templates = self.service.list_templates()
|
||
assert len(templates) >= 2
|
||
assert any(t.name == "GJB438C 软件需求规格说明书模板" for t in templates)
|
||
|
||
def test_create_template(self):
|
||
"""测试创建模板"""
|
||
new_tpl = Template(
|
||
name="测试模板",
|
||
template_type=TemplateType.SRS,
|
||
gjb_standard=GjbStandard.GJB438C,
|
||
)
|
||
result = self.service.create_template(new_tpl)
|
||
assert result.id is not None
|
||
assert result.name == "测试模板"
|
||
|
||
def test_get_template_not_found(self):
|
||
"""测试获取不存在的模板"""
|
||
result = self.service.get_template("NONEXIST")
|
||
assert result is None
|
||
|
||
def test_delete_template(self):
|
||
"""测试删除模板"""
|
||
assert self.service.delete_template("TPL-001") is True
|
||
assert self.service.delete_template("NONEXIST") is False
|
||
|
||
|
||
# =============================================================================
|
||
# 文档管理服务测试
|
||
# =============================================================================
|
||
|
||
class TestDocumentService:
|
||
"""文档管理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = DocumentService()
|
||
|
||
def test_list_documents(self):
|
||
"""测试获取文档列表"""
|
||
docs = self.service.list_documents()
|
||
assert len(docs) >= 2
|
||
|
||
def test_create_document(self):
|
||
"""测试创建文档"""
|
||
new_doc = Document(
|
||
title="测试文档",
|
||
template_id="TPL-001",
|
||
)
|
||
result = self.service.create_document(new_doc)
|
||
assert result.id is not None
|
||
assert result.status == DocumentStatus.DRAFT
|
||
|
||
def test_get_document(self):
|
||
"""测试获取文档详情"""
|
||
doc = self.service.get_document("DOC-001")
|
||
assert doc is not None
|
||
assert doc.title == "某型雷达系统软件需求规格说明书"
|
||
|
||
|
||
# =============================================================================
|
||
# GJB合规验证服务测试(SRS-MACP_F-002)
|
||
# =============================================================================
|
||
|
||
class TestGjbValidatorService:
|
||
"""GJB合规验证服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = GjbValidatorService()
|
||
self.doc_service = DocumentService()
|
||
|
||
def test_list_rules(self):
|
||
"""测试获取规则列表"""
|
||
rules = self.service.list_rules()
|
||
assert len(rules) >= 7
|
||
|
||
def test_validate_document(self):
|
||
"""测试文档合规验证"""
|
||
doc = self.doc_service.get_document("DOC-001")
|
||
assert doc is not None
|
||
report = self.service.validate_document(doc)
|
||
assert report.document_id == "DOC-001"
|
||
assert report.total_rules >= 7
|
||
assert isinstance(report.non_compliant_items, list)
|
||
|
||
|
||
# =============================================================================
|
||
# MCP工具管理服务测试(SRS-MACP_F-004)
|
||
# =============================================================================
|
||
|
||
class TestMcpToolService:
|
||
"""MCP工具管理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = McpToolService()
|
||
|
||
def test_list_tools(self):
|
||
"""测试获取MCP工具列表"""
|
||
tools = self.service.list_tools()
|
||
assert len(tools) >= 2
|
||
|
||
def test_register_tool(self):
|
||
"""测试注册MCP工具"""
|
||
new_tool = McpTool(
|
||
name="test_tool",
|
||
description="测试工具",
|
||
)
|
||
result = self.service.register_tool(new_tool)
|
||
assert result.id is not None
|
||
|
||
def test_debug_tool(self):
|
||
"""测试MCP工具调试"""
|
||
result = self.service.debug_tool("MCP-001", {"test": "data"})
|
||
assert result["success"] is True
|
||
|
||
def test_debug_tool_not_found(self):
|
||
"""测试调试不存在的工具"""
|
||
result = self.service.debug_tool("NONEXIST", {})
|
||
assert result["success"] is False
|
||
|
||
|
||
# =============================================================================
|
||
# Skills编排服务测试(SRS-MACP_F-005)
|
||
# =============================================================================
|
||
|
||
class TestSkillService:
|
||
"""Skills流程编排服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = SkillService()
|
||
|
||
def test_list_skills(self):
|
||
"""测试获取Skills列表"""
|
||
skills = self.service.list_skills()
|
||
assert len(skills) >= 2
|
||
|
||
def test_create_skill(self):
|
||
"""测试创建Skill"""
|
||
new_skill = Skill(
|
||
name="测试Skill",
|
||
prompt_template="测试模板",
|
||
)
|
||
result = self.service.create_skill(new_skill)
|
||
assert result.id is not None
|
||
|
||
def test_execute_skill(self):
|
||
"""测试执行Skill"""
|
||
result = self.service.execute_skill("SK-001", {"document_id": "DOC-001"})
|
||
assert result["success"] is True
|
||
assert result["skill_id"] == "SK-001"
|
||
|
||
def test_list_workflows(self):
|
||
"""测试获取工作流列表"""
|
||
workflows = self.service.list_workflows()
|
||
assert len(workflows) >= 1
|
||
|
||
|
||
# =============================================================================
|
||
# 智能体记忆管理服务测试(SRS-MACP_F-006)
|
||
# =============================================================================
|
||
|
||
class TestMemoryService:
|
||
"""智能体记忆管理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = MemoryService()
|
||
|
||
def test_list_memories(self):
|
||
"""测试获取记忆列表"""
|
||
memories = self.service.list_memories()
|
||
assert len(memories) >= 2
|
||
|
||
def test_create_memory(self):
|
||
"""测试创建记忆"""
|
||
new_mem = MemoryEntry(
|
||
session_id="SESS-TEST",
|
||
summary="测试记忆",
|
||
original_dialogue="测试对话内容",
|
||
memory_type=MemoryType.SHORT_TERM,
|
||
)
|
||
result = self.service.create_memory(new_mem)
|
||
assert result.id is not None
|
||
|
||
def test_search_memories(self):
|
||
"""测试搜索记忆"""
|
||
results = self.service.search_memories("GJB438C")
|
||
assert len(results) >= 1
|
||
|
||
def test_delete_memory(self):
|
||
"""测试删除记忆"""
|
||
assert self.service.delete_memory("MEM-001") is True
|
||
assert self.service.delete_memory("NONEXIST") is False
|
||
|
||
|
||
# =============================================================================
|
||
# 知识库交互服务测试(SRS-MACP_F-008)
|
||
# =============================================================================
|
||
|
||
class TestKnowledgeBaseService:
|
||
"""知识库交互服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = KnowledgeBaseService()
|
||
|
||
def test_list_chunks(self):
|
||
"""测试获取知识库片段"""
|
||
chunks = self.service.list_chunks()
|
||
assert len(chunks) >= 3
|
||
|
||
def test_list_chunks_by_level(self):
|
||
"""测试按层级过滤知识库片段"""
|
||
docs = self.service.list_chunks(KnowledgeLevel.DOCUMENT)
|
||
assert all(c.level == KnowledgeLevel.DOCUMENT for c in docs)
|
||
|
||
def test_search_chunks(self):
|
||
"""测试搜索知识库"""
|
||
results = self.service.search_chunks("GJB438C")
|
||
assert len(results) >= 1
|
||
|
||
def test_get_chunk_not_found(self):
|
||
"""测试获取不存在的知识库片段"""
|
||
result = self.service.get_chunk("NONEXIST")
|
||
assert result is None
|
||
|
||
|
||
# =============================================================================
|
||
# 大模型接入管理服务测试(SRS-MACP_F-009)
|
||
# =============================================================================
|
||
|
||
class TestModelService:
|
||
"""大模型接入管理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = ModelService()
|
||
|
||
def test_list_models(self):
|
||
"""测试获取模型配置列表"""
|
||
models = self.service.list_models()
|
||
assert len(models) >= 2
|
||
|
||
def test_get_primary_model(self):
|
||
"""测试获取主用模型"""
|
||
model = self.service.get_primary_model()
|
||
assert model is not None
|
||
assert model.is_primary is True
|
||
|
||
def test_health_check(self):
|
||
"""测试模型健康检查"""
|
||
result = self.service.health_check("MDL-001")
|
||
assert result["healthy"] is True
|
||
|
||
def test_failover(self):
|
||
"""测试模型故障转移"""
|
||
model = self.service.failover("MDL-001")
|
||
assert model is not None
|
||
assert model.is_primary is True
|
||
|
||
|
||
# =============================================================================
|
||
# 多模态处理服务测试(SRS-MACP_F-010)
|
||
# =============================================================================
|
||
|
||
class TestMultimodalService:
|
||
"""多模态输入处理服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = MultimodalService()
|
||
|
||
def test_process_image(self):
|
||
"""测试图片处理"""
|
||
result = self.service.process_file("test.jpg", FileType.IMAGE)
|
||
assert result.ocr_text is not None
|
||
assert result.file_type == FileType.IMAGE
|
||
|
||
def test_process_audio(self):
|
||
"""测试音频处理"""
|
||
result = self.service.process_file("test.mp3", FileType.AUDIO)
|
||
assert result.asr_transcript is not None
|
||
assert result.file_type == FileType.AUDIO
|
||
|
||
def test_process_video(self):
|
||
"""测试视频处理"""
|
||
result = self.service.process_file("test.mp4", FileType.VIDEO)
|
||
assert result.ocr_text is not None
|
||
assert result.asr_transcript is not None
|
||
assert len(result.key_frames) > 0
|
||
|
||
def test_get_result(self):
|
||
"""测试获取处理结果"""
|
||
result = self.service.process_file("test.png", FileType.IMAGE)
|
||
fetched = self.service.get_result(result.id)
|
||
assert fetched is not None
|
||
assert fetched.id == result.id
|
||
|
||
|
||
# =============================================================================
|
||
# 安全沙箱执行服务测试(SRS-MACP_F-007)
|
||
# =============================================================================
|
||
|
||
class TestSandboxService:
|
||
"""安全沙箱执行服务测试"""
|
||
|
||
def setup_method(self):
|
||
self.service = SandboxService()
|
||
|
||
def test_execute_code(self):
|
||
"""测试沙箱执行代码"""
|
||
result = self.service.execute_code("print('hello')", "python")
|
||
assert result["status"] == "completed"
|
||
assert result["execution_id"] is not None
|
||
|
||
def test_get_execution_logs(self):
|
||
"""测试获取执行日志"""
|
||
self.service.execute_code("x = 1 + 1", "python")
|
||
logs = self.service.get_execution_logs()
|
||
assert len(logs) >= 1
|
||
|
||
|
||
# =============================================================================
|
||
# API 接口集成测试
|
||
# =============================================================================
|
||
|
||
class TestApiEndpoints:
|
||
"""API 接口集成测试"""
|
||
|
||
def test_get_templates_api(self, client):
|
||
"""测试获取模板列表接口"""
|
||
response = client.get("/api/v1/templates")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == 200
|
||
assert len(data["data"]) >= 2
|
||
|
||
def test_create_template_api(self, client):
|
||
"""测试创建模板接口"""
|
||
payload = {
|
||
"name": "API测试模板",
|
||
"template_type": "SRS",
|
||
"gjb_standard": "GJB438C",
|
||
}
|
||
response = client.post("/api/v1/templates", json=payload)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["message"] == "模板创建成功"
|
||
|
||
def test_get_documents_api(self, client):
|
||
"""测试获取文档列表接口"""
|
||
response = client.get("/api/v1/documents")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == 200
|
||
|
||
def test_validate_document_api(self, client):
|
||
"""测试文档合规验证接口"""
|
||
response = client.post("/api/v1/documents/DOC-001/validate")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == 200
|
||
assert "验证完成" in data["message"]
|
||
|
||
def test_get_rules_api(self, client):
|
||
"""测试获取规则列表接口"""
|
||
response = client.get("/api/v1/rules")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == 200
|
||
|
||
def test_get_skills_api(self, client):
|
||
"""测试获取Skills列表接口"""
|
||
response = client.get("/api/v1/skills")
|
||
assert response.status_code == 200
|
||
|
||
def test_execute_skill_api(self, client):
|
||
"""测试执行Skill接口"""
|
||
response = client.post(
|
||
"/api/v1/skills/execute",
|
||
params={"skill_id": "SK-001"},
|
||
json={"document_id": "DOC-001"},
|
||
)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["data"]["success"] is True
|
||
|
||
def test_get_memory_api(self, client):
|
||
"""测试获取记忆列表接口"""
|
||
response = client.get("/api/v1/memory")
|
||
assert response.status_code == 200
|
||
|
||
def test_search_knowledge_api(self, client):
|
||
"""测试搜索知识库接口"""
|
||
response = client.post(
|
||
"/api/v1/knowledge/search",
|
||
params={"query": "GJB438C", "top_k": 3},
|
||
)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert len(data["data"]) >= 1
|
||
|
||
def test_get_models_api(self, client):
|
||
"""测试获取模型配置列表接口"""
|
||
response = client.get("/api/v1/models")
|
||
assert response.status_code == 200
|
||
|
||
def test_multimodal_process_api(self, client):
|
||
"""测试多模态处理接口"""
|
||
response = client.post(
|
||
"/api/v1/multimodal/process",
|
||
params={"file_name": "test.jpg", "file_type": "IMAGE"},
|
||
)
|
||
assert response.status_code == 200
|
||
|
||
def test_sandbox_execute_api(self, client):
|
||
"""测试沙箱执行接口"""
|
||
response = client.post(
|
||
"/api/v1/sandbox/execute",
|
||
params={"code": "print('hello')", "language": "python"},
|
||
)
|
||
assert response.status_code == 200
|
||
|
||
def test_mcp_tools_api(self, client):
|
||
"""测试获取MCP工具列表接口"""
|
||
response = client.get("/api/v1/mcp-tools")
|
||
assert response.status_code == 200
|
||
|
||
def test_404_error(self, client):
|
||
"""测试404错误"""
|
||
response = client.get("/api/v1/templates/NONEXIST")
|
||
assert response.status_code == 404
|
||
|
||
def test_get_workflows_api(self, client):
|
||
"""测试获取工作流列表接口"""
|
||
response = client.get("/api/v1/workflows")
|
||
assert response.status_code == 200
|
||
|
||
def test_get_mcp_tool_debug(self, client):
|
||
"""测试MCP工具调试接口"""
|
||
response = client.post(
|
||
"/api/v1/mcp-tools/MCP-001/debug",
|
||
json={"input": "test"},
|
||
)
|
||
assert response.status_code == 200
|