Files
AIPortPilot/backend/tests/test_phase34_agents.py
selfrelease fad458b2a7 docs(uiux): UIUX 设计方案大改 + 5 份作业指导书对齐 + 开发任务文档
- UIUX 文档:填充 19 个缺口(多主体画像/健康度/AI+看板/增长域/洞察域/创始人端/OODA/助推/商密)
- UIUX 文档:插入 6 个新章节(十四~十九),旧章节重编号为二十~三十一,更新目录和交叉引用
- 作业指导书 x5:导航改为 6 域分组,新增 Context Bar/工作模式/Insight Rail/决策线程/多工作区等 UI 概念
- 新建 docs/2-task-uiux.md:50 个代码落地开发任务,按 P0-P6 分优先级 + 8 Sprint 规划
- 后端/前端:大量新增模型、路由、组件(来自之前 Phase 开发)
2026-07-19 11:53:38 +08:00

274 lines
9.9 KiB
Python
Raw Permalink 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.
"""Phase 3-4 AI Agent Service 层测试。
测试所有依赖 LLM 的 AI Agent service
- synergy_matcher: 协同匹配
- alpha_attribution: Alpha 归因
- exit_predictor: 退出预测
- aar_agent: AAR 复盘
- digital_twin_engine: 数字孪生
- milestone_agent: 里程碑路径切换
- talent_agent: 人才流动预测
- board_agent: 董事会摘要
- innovation_discoverer: 组合创新
- knowledge_graph_builder: 知识图谱
- agent_orchestrator: Agent 编排
- portfolio_rebalancer: 组合再平衡(纯计算,无 LLM)
"""
import pytest
from app.services.synergy_matcher import match_synergy
from app.services.alpha_attribution import attribute_alpha
from app.services.exit_predictor import predict_exit
from app.services.aar_agent import generate_aar, check_aar_triggers
from app.services.digital_twin_engine import build_twin_model, simulate_scenario
from app.services.milestone_agent import suggest_path_switch
from app.services.talent_agent import predict_talent_flow, recommend_talent
from app.services.board_agent import generate_meeting_summary, generate_questions
from app.services.portfolio_rebalancer import (
calculate_marginal_return,
rebalance_portfolio,
run_monte_carlo,
)
from app.services.agent_orchestrator import orchestrate_agent
class TestSynergyMatcher:
"""协同匹配 Agent 测试。"""
@pytest.mark.asyncio
async def test_match_synergy_returns_list(self):
"""match_synergy 应返回 list。"""
result = await match_synergy("企业A需要数据标注", "企业B有数据标注团队")
assert isinstance(result, list)
@pytest.mark.asyncio
async def test_match_synergy_non_empty(self):
"""有匹配条件时应返回非空列表。"""
result = await match_synergy("企业A需要AI算力", "企业B有GPU集群")
assert len(result) >= 1
assert "type" in result[0]
class TestAlphaAttribution:
"""Alpha 归因 Agent 测试。"""
@pytest.mark.asyncio
async def test_attribute_returns_dict(self):
"""attribute_alpha 应返回 dict。"""
result = await attribute_alpha(
{"type": "战略建议", "description": "调整产品方向"},
{"revenue": "+20%", "users": "+15%"},
)
assert isinstance(result, dict)
@pytest.mark.asyncio
async def test_attribute_has_fields(self):
"""归因结果应包含关键字段。"""
result = await attribute_alpha({"type": "人才引进"}, {"headcount": "+10"})
assert "score" in result or "confidence" in result or "summary" in result
class TestExitPredictor:
"""退出预测 Agent 测试。"""
@pytest.mark.asyncio
async def test_predict_exit_returns_dict(self):
"""predict_exit 应返回 dict。"""
result = await predict_exit("企业估值5亿,年收入1亿,增长率30%")
assert isinstance(result, dict)
@pytest.mark.asyncio
async def test_predict_exit_non_empty(self):
"""退出预测结果应非空。"""
result = await predict_exit("企业估值5亿,年收入1亿,增长率30%")
assert len(result) > 0
class TestAARAgent:
"""AAR 复盘 Agent 测试。"""
@pytest.mark.asyncio
async def test_generate_aar_returns_dict(self):
"""generate_aar 应返回 dict。"""
result = await generate_aar(
"融资失败",
"计划Q2完成A轮融资5000万",
"仅获得2000万意向,未达成目标",
)
assert isinstance(result, dict)
@pytest.mark.asyncio
async def test_check_aar_triggers_funding(self):
"""融资完成事件应触发 AAR。"""
events = [
{"type": "funding_completed", "title": "A轮融资完成"},
{"type": "normal_event", "title": "例会"},
]
triggers = await check_aar_triggers("company-1", events)
assert len(triggers) == 1
assert triggers[0]["trigger_type"] == "funding_completed"
@pytest.mark.asyncio
async def test_check_aar_triggers_talent(self):
"""人才离职事件应触发 AAR。"""
events = [
{"type": "talent_left", "title": "CTO离职"},
]
triggers = await check_aar_triggers("company-1", events)
assert len(triggers) == 1
assert triggers[0]["trigger_type"] == "talent_left"
@pytest.mark.asyncio
async def test_check_aar_triggers_empty(self):
"""无触发事件时应返回空列表。"""
events = [
{"type": "normal_event", "title": "日常会议"},
]
triggers = await check_aar_triggers("company-1", events)
assert triggers == []
class TestDigitalTwinEngine:
"""数字孪生 Agent 测试。"""
@pytest.mark.asyncio
async def test_build_twin_model(self):
"""build_twin_model 应返回 dict。"""
result = await build_twin_model("企业A:年收入1亿,团队50人,产品SaaS")
assert isinstance(result, dict)
@pytest.mark.asyncio
async def test_simulate_scenario(self):
"""simulate_scenario 应返回 dict。"""
result = await simulate_scenario(
{"revenue_growth": 0.2, "burn_rate": 500000},
"市场下行20%",
)
assert isinstance(result, dict)
class TestMilestoneAgent:
"""里程碑 Agent 测试。"""
@pytest.mark.asyncio
async def test_suggest_path_switch(self):
"""suggest_path_switch 应返回 dict。"""
result = await suggest_path_switch(
"当前里程碑:产品MVP完成",
"竞品提前发布,市场窗口缩小",
)
assert isinstance(result, dict)
class TestTalentAgent:
"""人才 Agent 测试。"""
@pytest.mark.asyncio
async def test_predict_talent_flow(self):
"""predict_talent_flow 应返回 dict。"""
result = await predict_talent_flow("企业A50人,近期3人离职")
assert isinstance(result, dict)
@pytest.mark.asyncio
async def test_recommend_talent(self):
"""recommend_talent 应返回 list。"""
result = await recommend_talent("需要AI算法工程师", "人才池:张三、李四")
assert isinstance(result, list)
class TestBoardAgent:
"""董事会 Agent 测试。"""
@pytest.mark.asyncio
async def test_generate_meeting_summary(self):
"""generate_meeting_summary 应返回 str。"""
result = await generate_meeting_summary("Q3财报:收入增长20%,但利润下降")
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.asyncio
async def test_generate_questions(self):
"""generate_questions 应返回 list。"""
result = await generate_questions("Q3财报:收入增长20%,但利润下降")
assert isinstance(result, list)
class TestPortfolioRebalancer:
"""组合再平衡计算测试(纯计算,无 LLM 依赖)。"""
def test_calculate_marginal_return_positive(self):
"""正投资边际回报率应正确计算。"""
result = calculate_marginal_return(1000000, 500000, 0.2)
assert result > 0
assert result == 0.2 # 边际回报率 = 期望回报率
def test_calculate_marginal_return_zero_investment(self):
"""追加投资为 0 时边际回报率应为 0。"""
result = calculate_marginal_return(1000000, 0, 0.2)
assert result == 0.0
def test_rebalance_portfolio(self):
"""再平衡应按边际回报率排序。"""
companies = [
{"company_id": "c1", "marginal_return": 0.05},
{"company_id": "c2", "marginal_return": 0.15},
{"company_id": "c3", "marginal_return": 0.10},
{"company_id": "c4", "marginal_return": 0.02},
]
result = rebalance_portfolio(companies)
assert "reallocation_plan" in result
assert "increase" in result["reallocation_plan"]
assert "decrease" in result["reallocation_plan"]
# c2 (0.15) 应在 increase 中
assert "c2" in result["reallocation_plan"]["increase"]
# c4 (0.02) 应在 decrease 中
assert "c4" in result["reallocation_plan"]["decrease"]
def test_rebalance_empty(self):
"""空列表应返回空计划。"""
result = rebalance_portfolio([])
assert result["reallocation_plan"]["increase"] == []
assert result["reallocation_plan"]["decrease"] == []
def test_run_monte_carlo_with_floats(self):
"""纯 float 列表应正常模拟。"""
result = run_monte_carlo([0.15, 0.10, 0.05], iterations=100)
assert "irr_distribution" in result
assert "percentile_p5" in result
assert "percentile_p50" in result
assert "percentile_p95" in result
def test_run_monte_carlo_with_dicts(self):
"""dict 列表(含 irr 字段)应正常模拟。"""
result = run_monte_carlo(
[{"company_id": "c1", "irr": 0.15}, {"company_id": "c2", "irr": 0.08}],
iterations=100,
)
assert "irr_distribution" in result
assert result["percentile_p50"] > 0
def test_run_monte_carlo_empty(self):
"""空列表应返回零值。"""
result = run_monte_carlo([], iterations=100)
assert result["percentile_p5"] == 0
assert result["percentile_p50"] == 0
assert result["percentile_p95"] == 0
class TestAgentOrchestrator:
"""Agent 编排测试。"""
@pytest.mark.asyncio
async def test_orchestrate_low_autonomy(self):
"""低自治级别应标记需要人工审核。"""
result = await orchestrate_agent("test_agent", "low", {"task": "分析"})
assert isinstance(result, dict)
assert "needs_review" in result or "autonomy_level" in result or "status" in result
@pytest.mark.asyncio
async def test_orchestrate_high_autonomy(self):
"""高自治级别应直接执行。"""
result = await orchestrate_agent("test_agent", "high", {"task": "生成报告"})
assert isinstance(result, dict)