ForcePilot/backend/test/unit/channels/test_yuanbao_analysis.py
Kris 3264900bc9 test: 新增多渠道单元测试用例并配置测试环境变量
新增了Twitch、Telegram、Discord、Slack、Mattermost、WeChat、Zalo等多渠道的单元测试用例,覆盖了令牌处理、速率限制、消息去重、会话解析、格式转换、安全策略等模块
同时在测试配置中添加了测试用的OpenAI API密钥环境变量
2026-05-12 00:56:47 +08:00

233 lines
7.9 KiB
Python

from __future__ import annotations
import json
import time
from pathlib import Path
import pytest
from yuxi.channels.adapters.yuanbao.analysis.orchestrator import YuanbaoAnalyzer
from yuxi.channels.adapters.yuanbao.analysis.report_generator import GapReport, generate_gap_report
from yuxi.channels.adapters.yuanbao.analysis.sub_agents import (
AnalysisResult,
Finding,
SubAgentFunctionalResearch,
SubAgentIssueResearch,
SubAgentWebResearch,
)
class TestSubAgentWebResearch:
@pytest.mark.asyncio
async def test_research_returns_analysis_result(self):
agent = SubAgentWebResearch()
result = await agent.research()
assert isinstance(result, AnalysisResult)
assert result.agent_name == "WebResearchAgent"
assert result.category == "external_research"
assert len(result.findings) > 0
assert result.summary
assert "critical" in result.severity_counts
assert "warning" in result.severity_counts
@pytest.mark.asyncio
async def test_research_includes_platform_info(self):
agent = SubAgentWebResearch()
result = await agent.research()
titles = [f["title"] for f in result.findings]
assert any("月活" in t or "用户" in t or "MAU" in t for t in titles)
assert any("Hermes" in t or "OpenClaw" in t or "适配器" in t for t in titles)
class TestSubAgentFunctionalResearch:
@pytest.mark.asyncio
async def test_research_returns_analysis_result(self):
agent = SubAgentFunctionalResearch()
result = await agent.research()
assert isinstance(result, AnalysisResult)
assert result.agent_name == "FunctionalResearchAgent"
assert result.category == "code_functional_analysis"
assert len(result.findings) > 0
assert result.summary
@pytest.mark.asyncio
async def test_research_includes_module_files(self):
agent = SubAgentFunctionalResearch()
result = await agent.research()
files = [f for f in result.findings if f.get("file")]
file_names = [f["file"] for f in files]
assert "adapter.py" in file_names
assert "token.py" in file_names
assert "security.py" in file_names
@pytest.mark.asyncio
async def test_research_identifies_missing_features(self):
agent = SubAgentFunctionalResearch()
result = await agent.research()
missing = [f for f in result.findings if f.get("status") == "missing"]
assert len(missing) > 0
missing_titles = [f["title"] for f in missing]
assert any("send_media" in t for t in missing_titles)
@pytest.mark.asyncio
async def test_research_identifies_dead_code(self):
agent = SubAgentFunctionalResearch()
result = await agent.research()
dead = [f for f in result.findings if f.get("status") == "dead_code"]
assert len(dead) > 0
class TestSubAgentIssueResearch:
@pytest.mark.asyncio
async def test_research_returns_analysis_result(self):
agent = SubAgentIssueResearch()
result = await agent.research()
assert isinstance(result, AnalysisResult)
assert result.agent_name == "IssueResearchAgent"
assert result.category == "code_quality_and_bugs"
assert len(result.findings) > 0
assert result.summary
@pytest.mark.asyncio
async def test_research_finds_high_severity_issues(self):
agent = SubAgentIssueResearch()
result = await agent.research()
critical_or_warning = [f for f in result.findings
if f.get("severity") in ("critical", "warning")]
assert len(critical_or_warning) > 0
@pytest.mark.asyncio
async def test_research_finds_warning_issues(self):
agent = SubAgentIssueResearch()
result = await agent.research()
warnings = [f for f in result.findings if f.get("severity") == "warning"]
assert len(warnings) > 0
@pytest.mark.asyncio
async def test_finding_severity_counts_are_accurate(self):
agent = SubAgentIssueResearch()
result = await agent.research()
total_by_count = sum(result.severity_counts.values())
assert total_by_count == len(result.findings)
class TestFinding:
def test_finding_creation(self):
f = Finding(
file="test.py",
line=10,
severity="warning",
category="error_handling",
title="Test issue",
description="A test description",
suggestion="Fix it",
code_snippet="print('hello')",
)
assert f.file == "test.py"
assert f.line == 10
assert f.severity == "warning"
class TestReportGenerator:
def test_generate_gap_report_basic(self):
results = [
AnalysisResult(
agent_name="WebAgent",
category="external_research",
findings=[],
summary="Web research done",
),
AnalysisResult(
agent_name="FuncAgent",
category="code_functional_analysis",
findings=[
{"title": "Missing Feature X", "status": "missing", "detail": "Not implemented"},
{"title": "Implemented Feature Y", "status": "implemented", "detail": "Done"},
],
summary="Functional analysis done",
),
AnalysisResult(
agent_name="IssueAgent",
category="code_quality_and_bugs",
findings=[
{"file": "x.py", "line": 1, "severity": "critical", "category": "bug",
"title": "Bug 1", "description": "Bad bug",
"suggestion": "Fix it"},
],
summary="Issues found",
),
]
report = generate_gap_report(results)
assert isinstance(report, GapReport)
assert report.title
assert report.module_path == "yuxi/channels/adapters/yuanbao"
assert len(report.missing_features) > 0
assert len(report.bug_list) > 0
assert len(report.fix_plan) > 0
assert report.summary
class TestYuanbaoAnalyzer:
@pytest.mark.asyncio
async def test_run_full_analysis(self, tmp_path):
analyzer = YuanbaoAnalyzer(output_dir=str(tmp_path))
report = await analyzer.run_full_analysis()
assert isinstance(report, GapReport)
assert report.title
assert report.generated_at
assert report.summary
assert len(report.missing_features) > 0
assert len(report.unimplemented_interfaces) > 0
assert len(report.industry_gaps) > 0
assert len(report.security_issues) > 0
assert len(report.bug_list) > 0
assert len(report.fix_plan) > 0
@pytest.mark.asyncio
async def test_run_full_analysis_saves_report(self, tmp_path):
analyzer = YuanbaoAnalyzer(output_dir=str(tmp_path))
report = await analyzer.run_full_analysis()
report_path = tmp_path / "gap_analysis_report.json"
assert report_path.exists()
data = json.loads(report_path.read_text(encoding="utf-8"))
assert data["title"] == report.title
assert data["summary"] == report.summary
def test_print_report_does_not_raise(self, capsys):
analyzer = YuanbaoAnalyzer()
report = GapReport(
title="Test Report",
generated_at="2026-01-01",
module_path="test",
summary="Test summary",
missing_features=[{"feature": "F1", "detail": "d", "priority": "high"}],
security_issues=[
{"severity": "critical", "location": "x.py:1", "issue": "Bad",
"fix": "Do better"}
],
fix_plan=[{"priority": "P0", "action": "Fix bug"}],
)
analyzer.print_report(report)
captured = capsys.readouterr()
assert "Test Report" in captured.out
assert "F1" in captured.out