abd6329035
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
77 lines
3.1 KiB
Python
77 lines
3.1 KiB
Python
"""比价记录页后端概览聚合(admin 口径:外部缺失记为成功)。"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, date, datetime
|
|
|
|
import pytest
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
from app.admin.repositories import queries
|
|
from app.admin.repositories.comparison_outcome import admin_success_sql
|
|
from app.db.session import SessionLocal
|
|
from app.models.comparison import ComparisonRecord
|
|
|
|
|
|
def test_postgresql_duration_summary_uses_ordered_set_aggregates() -> None:
|
|
stmt = queries._comparison_duration_aggregate_stmt(
|
|
[], admin_success_sql(), (0.05, 0.5, 0.95, 0.99)
|
|
)
|
|
sql = str(
|
|
stmt.compile(
|
|
dialect=postgresql.dialect(),
|
|
compile_kwargs={"literal_binds": True},
|
|
)
|
|
)
|
|
assert sql.count("percentile_cont") == 4
|
|
# 口径按原始结局 coalesce,而非直接读 status 列
|
|
assert "coalesce" in sql.lower()
|
|
|
|
|
|
def test_summary_counts_external_gaps_as_success() -> None:
|
|
db = SessionLocal()
|
|
try:
|
|
# (trace_id, status 列[已 normalize], record_status[原始结局], total_ms, cost, saved)
|
|
rows = [
|
|
("sum-success", "success", "success", 1000, 1.0, 100),
|
|
("sum-below-min", "success", "below_minimum", 2000, 2.0, 0),
|
|
("sum-store-closed", "failed", "store_closed", 3000, None, 0),
|
|
("sum-store-not-found", "failed", "store_not_found", 4000, None, 0),
|
|
("sum-failed", "failed", "failed", 100_000, 3.0, 0),
|
|
("sum-cancelled", "cancelled", None, 5000, None, 0),
|
|
("sum-running", "running", None, 6000, None, 0),
|
|
]
|
|
for trace_id, status, record_status, total_ms, cost, saved in rows:
|
|
db.add(ComparisonRecord(
|
|
trace_id=trace_id,
|
|
status=status,
|
|
total_ms=total_ms,
|
|
llm_cost_yuan=cost,
|
|
saved_amount_cents=saved,
|
|
raw_payload={"record_status": record_status} if record_status else None,
|
|
created_at=datetime(2038, 1, 15, 12, tzinfo=UTC),
|
|
))
|
|
db.flush()
|
|
|
|
summary = queries.comparison_records_summary(
|
|
db, date_from=date(2038, 1, 15), date_to=date(2038, 1, 15)
|
|
)
|
|
|
|
# admin 成功 = success + below_minimum + store_closed + store_not_found = 4
|
|
assert summary["started"] == 7
|
|
assert summary["success"] == 4
|
|
assert summary["completed"] == 5 # 4 成功 + 1 纯 failed
|
|
assert summary["cancelled"] == 1
|
|
assert summary["success_rate"] == pytest.approx(4 / 6) # 分母 started - cancelled
|
|
assert summary["avg_token_cost"] == pytest.approx(2.0) # (1+2+3)/3
|
|
assert summary["lower_price_rate"] == pytest.approx(1 / 4) # 仅 sum-success saved>0
|
|
# 耗时统计集 = admin 成功的 total_ms [1000,2000,3000,4000]
|
|
assert summary["avg_duration_ms"] == 2500
|
|
assert summary["p5_duration_ms"] == 1150
|
|
assert summary["p50_duration_ms"] == 2500
|
|
assert summary["p95_duration_ms"] == 3850
|
|
assert summary["p99_duration_ms"] == 3970
|
|
assert summary["cancelled_p50_ms"] == 5000
|
|
finally:
|
|
db.rollback()
|
|
db.close()
|