diff --git a/tests/test_e2e_v27.py b/tests/test_e2e_v27.py index 0672e30..93623a1 100644 --- a/tests/test_e2e_v27.py +++ b/tests/test_e2e_v27.py @@ -716,21 +716,12 @@ class TestE9RealAgentDispatch: self.data_root = data_root def _make_ticker(self): - """创建含 Dispatcher + Spawner 的 Ticker(隔离 registry,只含当前项目)""" + """创建含 Dispatcher + Spawner 的 Ticker(真实 spawn)""" from src.blackboard.registry import ProjectRegistry from src.daemon.dispatcher import Dispatcher from src.daemon.spawner import AgentSpawner - import tempfile - self._tmp = Path(tempfile.mkdtemp(prefix="e2e-ticker-")) - registry = ProjectRegistry(self._tmp) - import shutil - src_dir = self.data_root / self.pid - dst_dir = self._tmp / self.pid - if src_dir.exists(): - shutil.copytree(src_dir, dst_dir) - registry.create_project(self.pid, f"E9-{self.pid}") - - self._spawner = AgentSpawner(dry_run=True) + registry = ProjectRegistry(self.data_root) + self._spawner = AgentSpawner(dry_run=False) dispatcher = Dispatcher( registered_agents=["zhangfei-dev", "jiangwei-infra", "simayi-challenger", "pangtong-fujunshi"], spawner=self._spawner, @@ -744,12 +735,12 @@ class TestE9RealAgentDispatch: ) def test_e91_simple_task_agent_execute(self, client): - """简单任务 → dispatch + spawn 成功(dry_run 模式)""" + """简单任务 → 真实 Agent 执行 → 等待完成""" tid = _tid() resp = client.post(f"/api/projects/{self.pid}/tasks", json={ "id": tid, "title": "E2E简单任务:echo hello", - "description": "请执行:echo hello", + "description": "请执行:echo hello,然后把输出写入黑板。这是E2E测试,完成后标记done。", "status": "pending", "assignee": "zhangfei-dev", "task_type": "coding", @@ -757,25 +748,36 @@ class TestE9RealAgentDispatch: }) assert resp.status_code == 200 - # 手动触发 tick(走调度 + dry_run spawn) + # 手动触发 tick(走调度 + 真实 spawn) ticker = self._make_ticker() result = asyncio.run(ticker.tick()) - # 验证 dispatch 成功(从 tick 结果 + spawner sessions) + # 验证 dispatch 成功 proj = result.get("projects", {}).get(self.pid, {}) assert proj.get("status") == "ok" dispatched = proj.get("dispatched", []) assert tid in dispatched, f"Task {tid} not dispatched, dispatched={dispatched}" - # 验证 dry_run spawn 有 session - assert len(self._spawner.active_sessions) > 0 or len(self._spawner._sessions) > 0 + + # 等待 Agent 完成(最多 180 秒) + db_path = self.data_root / self.pid / "blackboard.db" + bb = Blackboard(db_path) + for _ in range(36): + time.sleep(5) + t = bb.get_task(tid) + if t and t.status in ("done", "failed", "review"): + break + + t = bb.get_task(tid) + assert t is not None + assert t.status != "pending", f"Agent 未被调度,状态仍为 pending" def test_e92_review_task_dispatch(self, client): - """review 任务 → dispatch + spawn 成功(dry_run 模式)""" + """review 任务 → 真实 Agent 执行 → 等待完成""" tid = _tid() resp = client.post(f"/api/projects/{self.pid}/tasks", json={ "id": tid, "title": "E2E Review:检查代码", - "description": "请查看任务描述并回复你的评审意见。", + "description": "请查看任务描述并回复你的评审意见。这是E2E测试,简单回复即可。", "status": "pending", "assignee": "jiangwei-infra", "task_type": "review", @@ -789,7 +791,19 @@ class TestE9RealAgentDispatch: proj = result.get("projects", {}).get(self.pid, {}) dispatched = proj.get("dispatched", []) assert tid in dispatched, f"Review task {tid} not dispatched, dispatched={dispatched}" - assert len(self._spawner.active_sessions) > 0 or len(self._spawner._sessions) > 0 + + # 等待 Agent 完成(最多 180 秒) + db_path = self.data_root / self.pid / "blackboard.db" + bb = Blackboard(db_path) + for _ in range(36): + time.sleep(5) + t = bb.get_task(tid) + if t and t.status in ("done", "failed", "review", "working", "claimed"): + break + + t = bb.get_task(tid) + assert t is not None + assert t.status != "pending", f"Review Agent 未被调度,状态仍为 pending" # ===================================================================