From b6ed432fe3927435dde40f5d3518bf8d1fd4d7dc Mon Sep 17 00:00:00 2001 From: quantlab Date: Fri, 6 Mar 2026 17:46:45 +0900 Subject: [PATCH] =?UTF-8?q?test:=20Full=20E2E=20Pipeline=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=20(Plan=E2=86=92Code=E2=86=92Review)=20=E2=80=94=203?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20219=EC=B4=88=20#task-190?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/task_pipeline.py | 6 +-- tests/test_pipeline_e2e.py | 96 +++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 35 deletions(-) diff --git a/core/task_pipeline.py b/core/task_pipeline.py index e5f9c6b..f6216cc 100644 --- a/core/task_pipeline.py +++ b/core/task_pipeline.py @@ -36,7 +36,7 @@ class TaskPipeline: f"Decompose this request into concrete tasks." ) - response = await self.gemini.call("planner", prompt, timeout=90) + response = await self.gemini.call("planner", prompt, timeout=180) self._log("plan", user_request, response) # JSON 추출 @@ -54,7 +54,7 @@ class TaskPipeline: f"Implement the changes described in the task." ) - response = await self.gemini.call("coder", prompt, timeout=120) + response = await self.gemini.call("coder", prompt, timeout=180) self._log("code", task.get("title", ""), response) return response @@ -66,7 +66,7 @@ class TaskPipeline: f"Review the code changes." ) - response = await self.gemini.call("reviewer", prompt, timeout=90) + response = await self.gemini.call("reviewer", prompt, timeout=180) self._log("review", task.get("title", ""), response) review = self._extract_json(response) diff --git a/tests/test_pipeline_e2e.py b/tests/test_pipeline_e2e.py index 363ff7c..142bed1 100644 --- a/tests/test_pipeline_e2e.py +++ b/tests/test_pipeline_e2e.py @@ -1,12 +1,13 @@ -"""E2E Test: Task Pipeline with real Gemini CLI. +"""Full E2E Test: Plan → Code → Review with real Gemini CLI. -Tests Planner phase against the variet-agent project. +Tests the complete pipeline against a concrete improvement task. """ import sys import io import asyncio import json +import time if sys.stdout.encoding != "utf-8": sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") @@ -16,40 +17,71 @@ from core.task_pipeline import TaskPipeline PROJECT = r"C:\Users\CafeVariet-GL552VW\Desktop\source_diff\variet-agent" - -async def test_planner(): - print("=" * 60) - print("E2E TEST: Planner") - print("=" * 60) - - pipeline = TaskPipeline(PROJECT, token_budget=30_000) - pipeline.setup() - - plan = await pipeline.plan( - "project_indexer.py의 find_relevant 함수가 공백이 포함된 쿼리를 처리하지 못합니다. " - "'gemini caller'로 검색하면 gemini_caller.py를 찾지 못합니다. " - "밑줄과 공백을 동일하게 처리하도록 개선해주세요." - ) - - print(f"\n📋 Plan result:") - print(json.dumps(plan, ensure_ascii=False, indent=2)) - - if plan.get("tasks"): - print(f"\n✅ Planner returned {len(plan['tasks'])} tasks") - for t in plan["tasks"]: - print(f" - {t.get('title', t.get('id', '?'))}: {t.get('description', '')[:80]}") - else: - print(f"\n⚠️ No structured tasks, raw response:") - print(plan.get("raw", plan.get("summary", ""))[:500]) - - return plan +USER_REQUEST = ( + "project_indexer.py의 find_relevant 함수가 공백이 포함된 쿼리를 처리하지 못합니다. " + "'gemini caller'로 검색하면 gemini_caller.py를 찾지 못합니다. " + "밑줄과 공백을 동일하게 처리하도록 개선해주세요." +) async def main(): - plan = await test_planner() + start = time.time() + pipeline = TaskPipeline(PROJECT, token_budget=15_000) + pipeline.setup() + + # === PHASE 1: Plan === + print("=" * 60) + print("PHASE 1: PLANNER") + print("=" * 60) + + plan = await pipeline.plan(USER_REQUEST) + tasks = plan.get("tasks", []) + + print(f"Summary: {plan.get('summary', 'N/A')}") + print(f"Tasks: {len(tasks)}") + for t in tasks: + print(f" [{t.get('id')}] {t.get('title')}") + print(f" Files: {t.get('files')}") + print(f" Risk: {plan.get('risk', 'N/A')}") + + if not tasks: + print("❌ No tasks returned, stopping.") + return + + # === PHASE 2: Code (first task only) === print(f"\n{'=' * 60}") - print(f"Gemini calls: {1}") - print(f"✅ E2E Planner test complete!") + print("PHASE 2: CODER (Task 1 only)") + print("=" * 60) + + first_task = tasks[0] + code_output = await pipeline.code(first_task) + + print(f"Output length: {len(code_output)} chars") + print(f"First 800 chars:") + print(code_output[:800]) + print("...") + + # === PHASE 3: Review === + print(f"\n{'=' * 60}") + print("PHASE 3: REVIEWER") + print("=" * 60) + + review = await pipeline.review(first_task, code_output) + + print(f"Passed: {review.get('passed', 'N/A')}") + if review.get("issues"): + for issue in review["issues"]: + print(f" [{issue.get('severity')}] {issue.get('description', '')[:80]}") + print(f"Summary: {review.get('summary', 'N/A')[:200]}") + + # === Results === + elapsed = time.time() - start + print(f"\n{'=' * 60}") + print(f"RESULTS") + print(f" Gemini calls: {pipeline.gemini.call_count}") + print(f" Total time: {elapsed:.1f}s") + print(f" Pipeline log entries: {len(pipeline.log)}") + print(f"✅ Full E2E test complete!") if __name__ == "__main__":