108 lines
4.1 KiB
Python
108 lines
4.1 KiB
Python
import asyncio
|
|
import unittest
|
|
from types import SimpleNamespace
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
from app.services.ai_steward import AIStewardService
|
|
from app.models import CognitiveConflict
|
|
|
|
|
|
class AIStewardFailFastTest(unittest.IsolatedAsyncioTestCase):
|
|
async def test_analyze_project_input_times_out_to_structured_fallback(self) -> None:
|
|
service = AIStewardService(db=None) # type: ignore[arg-type]
|
|
|
|
with patch.object(service.llm, "generate", AsyncMock(side_effect=asyncio.TimeoutError())):
|
|
result = await service._analyze_project_input(
|
|
"创建一个 3 周上线的 AI 客服项目,先出可运行 MVP。",
|
|
tenant_id=1,
|
|
)
|
|
|
|
self.assertEqual(result["primary_role"], "ai_engineer")
|
|
self.assertEqual(result["timeline"], "3周")
|
|
|
|
async def test_generate_task_chain_draft_times_out_to_default_tasks(self) -> None:
|
|
service = AIStewardService(db=None) # type: ignore[arg-type]
|
|
|
|
with patch.object(service.llm, "generate", AsyncMock(side_effect=asyncio.TimeoutError())):
|
|
tasks = await service._generate_task_chain_draft(
|
|
analysis={
|
|
"project_title": "AI 客服项目",
|
|
"tech_stack": ["FastAPI", "React"],
|
|
"timeline": "3周",
|
|
"primary_role": "ai_engineer",
|
|
},
|
|
tenant_id=1,
|
|
)
|
|
|
|
self.assertGreaterEqual(len(tasks), 2)
|
|
self.assertEqual(tasks[0]["title"], "技术方案设计")
|
|
|
|
async def test_persist_project_creation_draft_writes_conflict_user_ids_as_list(self) -> None:
|
|
added_rows = []
|
|
|
|
class FakeDB:
|
|
def add(self, row):
|
|
added_rows.append(row)
|
|
|
|
async def flush(self):
|
|
current = len(added_rows)
|
|
for index, row in enumerate(added_rows, start=1):
|
|
if getattr(row, "id", None) is None:
|
|
row.id = index
|
|
|
|
service = AIStewardService(db=FakeDB()) # type: ignore[arg-type]
|
|
|
|
with patch(
|
|
"app.services.ai_steward.persist_task",
|
|
AsyncMock(
|
|
return_value=SimpleNamespace(
|
|
id=101,
|
|
title="任务A",
|
|
description="desc",
|
|
estimated_hours=8.0,
|
|
priority="high",
|
|
status="todo",
|
|
)
|
|
),
|
|
):
|
|
payload = await service._persist_project_creation_draft(
|
|
normalized={
|
|
"project": {
|
|
"name": "测试项目",
|
|
"title": "测试项目",
|
|
"description": "desc",
|
|
"assigned_role": "ai_engineer",
|
|
"domain_id": 1,
|
|
},
|
|
"signal": {
|
|
"content": "signal",
|
|
"impact_score": 0.8,
|
|
"priority": "high",
|
|
"strategic_analysis": {},
|
|
},
|
|
"charter": {
|
|
"title": "项目宪章",
|
|
"content": {"success_criteria": ["ok"]},
|
|
},
|
|
"tasks": [SimpleNamespace(title="任务A", description="desc")],
|
|
"task_audit": [],
|
|
"risks": [
|
|
{
|
|
"type": "schedule_delay",
|
|
"description": "任务超时预警",
|
|
"threshold_hours": 48.0,
|
|
"severity": "medium",
|
|
}
|
|
],
|
|
"analysis": {},
|
|
},
|
|
input_text="创建测试项目",
|
|
creator_id=2,
|
|
tenant_id=1,
|
|
)
|
|
|
|
risk_rows = [row for row in added_rows if isinstance(row, CognitiveConflict)]
|
|
self.assertEqual(len(risk_rows), 1)
|
|
self.assertEqual(risk_rows[0].involved_user_ids, [])
|
|
self.assertEqual(payload["risks"][0]["description"], "任务超时预警")
|