AgentEvalTool/tests/integration/test_reports_api.py
sinohqb 5ecb30876e style(tests): ruff 全量清理 — 49 项修复,backend 与 tests 全绿
- ruff --fix 自动修正 44 项:移除未用 import(pytest 等)、import 块排序归一(I001)
- 手工修复剩余 5 项:test_cascade.py 两处未用赋值(F841);test_s2_rules_and_logic.py 中部 import 移至文件顶部(E402 ×3)
- 无行为变更:全量 492 项测试通过
2026-08-03 15:13:24 +08:00

217 lines
6.7 KiB
Python
Raw 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.

"""Integration tests for the reports API: /api/reports/{id}, /markdown, /compare."""
import json
import pytest
from agenteval.models import (
Case,
CaseType,
ChannelType,
EvalResult,
EvalRun,
EvalTarget,
PlatformType,
RunStatus,
Scenario,
TargetStatus,
Turn,
)
from agenteval.storage.repository import ResultRepository, RunRepository, ScenarioRepository, TargetRepository
from agenteval.web.app import app
from agenteval.web.deps import get_db
from fastapi.testclient import TestClient
from sqlmodel import Session, SQLModel, create_engine
@pytest.fixture()
def client_with_db(tmp_path):
from agenteval.storage.db import ( # noqa: F401
EvalResultDB,
EvalRunDB,
EvalTargetDB,
FileCategoryDB,
FileRecordDB,
ScenarioDB,
TurnDB,
)
engine = create_engine(
f"sqlite:///{tmp_path / 'reports_api.db'}",
connect_args={"check_same_thread": False},
)
SQLModel.metadata.create_all(engine)
session = Session(engine)
def override_get_db():
try:
yield session
finally:
pass
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
yield client, session
app.dependency_overrides.clear()
session.close()
def _seed_run(
session: Session,
name_suffix: str = "",
scenario_id: str | None = None,
scenario_version: int = 1,
) -> str:
target = EvalTarget(
name=f"target{name_suffix}",
platform=PlatformType.AI_DIGITAL_EMPLOYEE,
channel_type=ChannelType.TUTU_API,
channel_config={},
status=TargetStatus.ACTIVE,
)
target = TargetRepository(session).create(target)
if scenario_id is None:
scenario = Scenario(
name=f"scenario{name_suffix}",
cases=[Case(id="c1", type=CaseType.SINGLE, messages=["hi"])],
)
scenario = ScenarioRepository(session).create(scenario)
scenario_id = scenario.id
run = EvalRun(
target_id=target.id,
scenario_id=scenario_id,
scenario_version=scenario_version,
status=RunStatus.COMPLETED,
)
run = RunRepository(session).create(run)
result_repo = ResultRepository(session)
run_repo = RunRepository(session)
turn = Turn(
run_id=run.id, case_id="c1", round_index=1,
sent_message={"msgBody": {"content": "问题"}},
reply={"msgBody": {"content": "回答"}},
latency_ms=300,
)
result_repo.save_turn(turn)
db_turn = run_repo.get_turns(run.id)[0]
result_repo.save_result(EvalResult(
run_id=run.id, case_id="c1",
turn_id=db_turn.id or "",
rule_type="response_time",
passed=True, score=0.9, reason="",
))
run.summary = {
"total_cases": 1, "passed_cases": 1, "failed_cases": 0,
"total_rules": 1, "passed_rules": 1, "pass_rate": 1.0,
}
RunRepository(session).update(run)
return run.id
def test_get_report_200(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/{run_id}")
assert resp.status_code == 200
data = resp.json()
assert data["run_id"] == run_id
assert data["summary"]["pass_rate"] == 1.0
def test_get_report_404(client_with_db):
client, _ = client_with_db
resp = client.get("/api/reports/no-such-run")
assert resp.status_code == 404
def test_get_html_report(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/{run_id}/html")
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]
assert "评测报告" in resp.text
def test_get_json_report(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/{run_id}/json")
assert resp.status_code == 200
data = json.loads(resp.text)
assert "run_id" in data
def test_get_markdown_report(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/{run_id}/markdown")
assert resp.status_code == 200
assert "text/markdown" in resp.headers["content-type"]
assert "# 评测报告" in resp.text
assert "## 汇总" in resp.text
def test_get_markdown_report_attachment_header(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/{run_id}/markdown")
assert "attachment" in resp.headers.get("content-disposition", "")
def test_compare_report(client_with_db):
client, session = client_with_db
run_id_a = _seed_run(session, "A")
sid = RunRepository(session).get(run_id_a).scenario_id
run_id_b = _seed_run(session, "B", scenario_id=sid)
resp = client.get(f"/api/reports/compare?run1={run_id_a}&run2={run_id_b}")
assert resp.status_code == 200
data = resp.json()
assert data["run_a"]["run_id"] == run_id_a
assert data["run_b"]["run_id"] == run_id_b
assert "delta" in data
assert "cases" in data
def test_compare_report_different_scenarios_400(client_with_db):
client, session = client_with_db
run_id_a = _seed_run(session, "A")
run_id_b = _seed_run(session, "B") # separate scenario
resp = client.get(f"/api/reports/compare?run1={run_id_a}&run2={run_id_b}")
assert resp.status_code == 400
assert "相同场景" in resp.json()["detail"]
def test_compare_report_cross_version_400(client_with_db):
"""同场景不同考纲版本 → 400提示含双方版本号ticket 05 / ADR-0001"""
client, session = client_with_db
run_id_a = _seed_run(session, "A")
sid = RunRepository(session).get(run_id_a).scenario_id
run_id_b = _seed_run(session, "B", scenario_id=sid, scenario_version=2)
resp = client.get(f"/api/reports/compare?run1={run_id_a}&run2={run_id_b}")
assert resp.status_code == 400
detail = resp.json()["detail"]
assert "v1" in detail and "v2" in detail
def test_compare_report_same_version_ok(client_with_db):
client, session = client_with_db
run_id_a = _seed_run(session, "A", scenario_version=3)
sid = RunRepository(session).get(run_id_a).scenario_id
run_id_b = _seed_run(session, "B", scenario_id=sid, scenario_version=3)
resp = client.get(f"/api/reports/compare?run1={run_id_a}&run2={run_id_b}")
assert resp.status_code == 200
assert resp.json()["run_a"]["scenario_version"] == 3
assert resp.json()["run_b"]["scenario_version"] == 3
def test_compare_report_run_not_found(client_with_db):
client, session = client_with_db
run_id = _seed_run(session)
resp = client.get(f"/api/reports/compare?run1={run_id}&run2=ghost-id")
assert resp.status_code == 404