Files
multiAgentTry/backend/test_all_services.py
Claude Code dc398d7c7b 完整实现 Swarm 多智能体协作系统
- 新增 CLIPluginAdapter 统一接口 (backend/app/core/agent_adapter.py)
- 新增 LLM 服务层,支持 Anthropic/OpenAI/DeepSeek/Ollama (backend/app/services/llm_service.py)
- 新增 Agent 执行引擎,支持文件锁自动管理 (backend/app/services/agent_executor.py)
- 新增 NativeLLMAgent 原生 LLM 适配器 (backend/app/adapters/native_llm_agent.py)
- 新增进程管理器 (backend/app/services/process_manager.py)
- 新增 Agent 控制 API (backend/app/routers/agents_control.py)
- 新增 WebSocket 实时通信 (backend/app/routers/websocket.py)
- 更新前端 AgentsPage,支持启动/停止 Agent
- 测试通过:Agent 启动、批量操作、栅栏同步

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:32:11 +08:00

386 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
后端服务完整测试脚本
测试所有 10 个步骤的服务是否正常工作
"""
import asyncio
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from app.services.storage import get_storage
from app.services.file_lock import get_file_lock_service
from app.services.heartbeat import get_heartbeat_service
from app.services.agent_registry import get_agent_registry
from app.services.meeting_scheduler import get_meeting_scheduler
from app.services.meeting_recorder import get_meeting_recorder
from app.services.resource_manager import get_resource_manager
from app.services.workflow_engine import get_workflow_engine
from app.services.role_allocator import get_role_allocator
async def test_storage_service():
"""测试存储服务"""
print("\n=== 测试 StorageService ===")
storage = get_storage()
# 测试写入
await storage.write_json("cache/test_storage.json", {"test": "data", "number": 42})
print("[PASS] 写入 JSON 文件")
# 测试读取
data = await storage.read_json("cache/test_storage.json")
assert data["test"] == "data", "读取数据不匹配"
print("[PASS] 读取 JSON 文件")
# 测试存在检查
exists = await storage.exists("cache/test_storage.json")
assert exists, "文件应该存在"
print("[PASS] 文件存在检查")
# 测试删除
await storage.delete("cache/test_storage.json")
exists = await storage.exists("cache/test_storage.json")
assert not exists, "文件应该已被删除"
print("[PASS] 删除文件")
print("StorageService 测试通过")
return True
async def test_file_lock_service():
"""测试文件锁服务"""
print("\n=== 测试 FileLockService ===")
service = get_file_lock_service()
# 测试获取锁
success = await service.acquire_lock("src/test/file.py", "agent-001", "TestAgent")
assert success, "应该成功获取锁"
print("[PASS] 获取文件锁")
# 测试检查锁定
locked_by = await service.check_locked("src/test/file.py")
assert locked_by == "agent-001", "锁持有者应该匹配"
print("[PASS] 检查文件锁定状态")
# 测试其他 Agent 无法获取
success = await service.acquire_lock("src/test/file.py", "agent-002", "OtherAgent")
assert not success, "其他 Agent 不应该能获取已被锁定的文件"
print("[PASS] 冲突检测正常工作")
# 测试获取所有锁
locks = await service.get_locks()
assert len(locks) >= 1, "应该有至少一个锁"
print("[PASS] 获取所有锁列表")
# 测试释放锁
success = await service.release_lock("src/test/file.py", "agent-001")
assert success, "应该成功释放锁"
print("[PASS] 释放文件锁")
print("FileLockService 测试通过")
return True
async def test_heartbeat_service():
"""测试心跳服务"""
print("\n=== 测试 HeartbeatService ===")
service = get_heartbeat_service()
# 测试更新心跳
await service.update_heartbeat("agent-001", "working", "测试任务", 50)
print("[PASS] 更新心跳")
# 测试获取心跳
hb = await service.get_heartbeat("agent-001")
assert hb is not None, "心跳信息应该存在"
assert hb.status == "working", "状态应该匹配"
assert hb.progress == 50, "进度应该匹配"
print("[PASS] 获取心跳信息")
# 测试获取所有心跳
all_hbs = await service.get_all_heartbeats()
assert "agent-001" in all_hbs, "应该在所有心跳列表中"
print("[PASS] 获取所有心跳")
# 测试活跃 Agent
active = await service.get_active_agents(within_seconds=10)
assert "agent-001" in active, "应该是活跃 Agent"
print("[PASS] 获取活跃 Agent")
print("HeartbeatService 测试通过")
return True
async def test_agent_registry():
"""测试 Agent 注册服务"""
print("\n=== 测试 AgentRegistry ===")
registry = get_agent_registry()
# 测试注册 Agent
agent = await registry.register_agent(
"test-agent-001",
"Test Agent",
"developer",
"claude-opus-4.6",
"测试用的 Agent"
)
assert agent.agent_id == "test-agent-001", "ID 应该匹配"
print("[PASS] 注册 Agent")
# 测试获取 Agent
fetched = await registry.get_agent("test-agent-001")
assert fetched is not None, "应该能获取到 Agent"
assert fetched.name == "Test Agent", "名称应该匹配"
print("[PASS] 获取 Agent 信息")
# 测试更新状态
await registry.update_state("test-agent-001", "修复 bug", 75)
print("[PASS] 更新 Agent 状态")
# 测试获取状态
state = await registry.get_state("test-agent-001")
assert state is not None, "状态应该存在"
assert state.progress == 75, "进度应该匹配"
print("[PASS] 获取 Agent 状态")
# 测试列出所有 Agent
agents = await registry.list_agents()
assert len(agents) >= 1, "应该至少有一个 Agent"
print("[PASS] 列出所有 Agent")
print("AgentRegistry 测试通过")
return True
async def test_meeting_scheduler():
"""测试会议调度器"""
print("\n=== 测试 MeetingScheduler ===")
scheduler = get_meeting_scheduler()
# 测试创建会议
queue = await scheduler.create_meeting(
"test-meeting-001",
"测试会议",
["agent-001", "agent-002"],
min_required=2
)
assert queue.meeting_id == "test-meeting-001", "ID 应该匹配"
print("[PASS] 创建会议")
# 测试获取队列
fetched = await scheduler.get_queue("test-meeting-001")
assert fetched is not None, "队列应该存在"
print("[PASS] 获取会议队列")
# 测试等待会议(模拟两个 Agent 到达)
result1 = await scheduler.wait_for_meeting("agent-001", "test-meeting-001", timeout=1)
print(f" Agent-1 到达: {result1}")
result2 = await scheduler.wait_for_meeting("agent-002", "test-meeting-001", timeout=1)
print(f" Agent-2 到达: {result2}")
# 最后一个到达者应该触发会议开始
assert result2 == "started", "最后一个到达者应该触发会议开始"
print("[PASS] 栅栏同步工作正常")
# 测试结束会议
success = await scheduler.end_meeting("test-meeting-001")
assert success, "应该成功结束会议"
print("[PASS] 结束会议")
print("MeetingScheduler 测试通过")
return True
async def test_meeting_recorder():
"""测试会议记录服务"""
print("\n=== 测试 MeetingRecorder ===")
recorder = get_meeting_recorder()
# 测试创建会议记录
meeting = await recorder.create_meeting(
"test-record-001",
"测试记录会议",
["agent-001", "agent-002"],
["步骤1", "步骤2", "步骤3"]
)
assert meeting.meeting_id == "test-record-001", "ID 应该匹配"
assert len(meeting.steps) == 3, "应该有 3 个步骤"
print("[PASS] 创建会议记录")
# 测试添加讨论
await recorder.add_discussion("test-record-001", "agent-001", "Agent1", "这是第一条讨论")
await recorder.add_discussion("test-record-001", "agent-002", "Agent2", "这是第二条讨论")
print("[PASS] 添加讨论记录")
# 测试更新进度
await recorder.update_progress("test-record-001", "步骤1")
print("[PASS] 更新会议进度")
# 测试获取会议
fetched = await recorder.get_meeting("test-record-001")
assert fetched is not None, "会议应该存在"
assert len(fetched.discussions) == 2, "应该有 2 条讨论"
print("[PASS] 获取会议详情")
# 测试结束会议
success = await recorder.end_meeting("test-record-001", "达成共识:继续开发")
assert success, "应该成功结束会议"
print("[PASS] 结束会议并保存共识")
print("MeetingRecorder 测试通过")
return True
async def test_resource_manager():
"""测试资源管理器"""
print("\n=== 测试 ResourceManager ===")
manager = get_resource_manager()
# 测试解析任务文件
files = await manager.parse_task_files("修复 src/auth/login.py 和 src/utils/helper.js 中的 bug")
assert "src/auth/login.py" in files or "src/utils/helper.js" in files, "应该能解析出文件路径"
print(f"[PASS] 解析任务文件: {files}")
# 测试获取 Agent 状态(需要先有注册的 Agent
try:
status = await manager.get_agent_status("test-agent-001")
print(f"[PASS] 获取 Agent 状态: {status['agent_id']}")
except Exception as e:
print(f" [WARN] 获取状态警告: {e}")
print("ResourceManager 测试通过")
return True
async def test_workflow_engine():
"""测试工作流引擎"""
print("\n=== 测试 WorkflowEngine ===")
engine = get_workflow_engine()
# 确保测试工作流文件存在
workflow_content = """
workflow_id: "test-workflow"
name: "测试工作流"
description: "用于测试的工作流"
meetings:
- meeting_id: "step1"
title: "第一步"
attendees: ["agent-001"]
depends_on: []
- meeting_id: "step2"
title: "第二步"
attendees: ["agent-001", "agent-002"]
depends_on: ["step1"]
"""
import aiofiles
from pathlib import Path
workflow_path = Path(engine._storage.base_path) / "workflow" / "test.yaml"
async with aiofiles.open(workflow_path, mode="w", encoding="utf-8") as f:
await f.write(workflow_content)
# 测试加载工作流
workflow = await engine.load_workflow("test.yaml")
assert workflow.workflow_id == "test-workflow", "ID 应该匹配"
assert len(workflow.meetings) == 2, "应该有 2 个会议"
print("[PASS] 加载工作流")
# 测试获取下一个会议
next_meeting = await engine.get_next_meeting("test-workflow")
assert next_meeting is not None, "应该有下一个会议"
assert next_meeting.meeting_id == "step1", "第一个会议应该是 step1"
print("[PASS] 获取下一个会议")
# 测试完成会议
success = await engine.complete_meeting("test-workflow", "step1")
assert success, "应该成功标记会议完成"
print("[PASS] 标记会议完成")
# 测试获取工作流状态
status = await engine.get_workflow_status("test-workflow")
assert status is not None, "状态应该存在"
assert status["progress"] == "1/2", "进度应该是 1/2"
print("[PASS] 获取工作流状态")
print("WorkflowEngine 测试通过")
return True
async def test_role_allocator():
"""测试角色分配器"""
print("\n=== 测试 RoleAllocator ===")
allocator = get_role_allocator()
# 测试获取主要角色
primary = allocator.get_primary_role("实现登录功能并编写测试用例")
assert primary in ["pm", "developer", "qa", "architect", "reviewer"], "应该是有效角色"
print(f"[PASS] 获取主要角色: {primary}")
# 测试角色分配
allocation = await allocator.allocate_roles(
"设计数据库架构并实现 API",
["claude-001", "kimi-002", "opencode-003"]
)
assert len(allocation) == 3, "应该为 3 个 Agent 分配角色"
print(f"[PASS] 角色分配: {allocation}")
# 测试解释分配
explanation = allocator.explain_allocation("修复 bug", allocation)
assert "主要角色" in explanation, "解释应该包含主要角色"
print("[PASS] 解释角色分配")
print("RoleAllocator 测试通过")
return True
async def run_all_tests():
"""运行所有测试"""
print("=" * 60)
print("Swarm Command Center - 后端服务完整测试")
print("=" * 60)
tests = [
("StorageService", test_storage_service),
("FileLockService", test_file_lock_service),
("HeartbeatService", test_heartbeat_service),
("AgentRegistry", test_agent_registry),
("MeetingScheduler", test_meeting_scheduler),
("MeetingRecorder", test_meeting_recorder),
("ResourceManager", test_resource_manager),
("WorkflowEngine", test_workflow_engine),
("RoleAllocator", test_role_allocator),
]
results = []
for name, test_func in tests:
try:
success = await test_func()
results.append((name, success, None))
except Exception as e:
print(f"[FAIL] {name} 测试失败: {e}")
import traceback
traceback.print_exc()
results.append((name, False, str(e)))
# 打印总结
print("\n" + "=" * 60)
print("测试结果总结")
print("=" * 60)
passed = sum(1 for _, success, _ in results if success)
total = len(results)
for name, success, error in results:
status = "[PASS]" if success else f"[FAIL: {error}]"
print(f"{name:20s} {status}")
print("=" * 60)
print(f"总计: {passed}/{total} 通过")
print("=" * 60)
return passed == total
if __name__ == "__main__":
success = asyncio.run(run_all_tests())
sys.exit(0 if success else 1)