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 开发)
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""T4.10 智能预警 + 预测分析测试。"""
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.services.predictor import predict_trend, detect_anomalies
|
||||
|
||||
|
||||
class TestPredictTrend:
|
||||
"""趋势预测函数测试。"""
|
||||
|
||||
def test_predict_with_sufficient_data(self):
|
||||
"""有足够历史数据时应返回预测。"""
|
||||
result = predict_trend([60, 62, 65, 68, 70], months_ahead=3)
|
||||
assert "predicted" in result
|
||||
assert len(result["predicted"]) == 3
|
||||
assert all(0 <= p <= 100 for p in result["predicted"])
|
||||
assert result["confidence"] > 0
|
||||
|
||||
def test_predict_with_insufficient_data(self):
|
||||
"""数据不足时应返回空预测。"""
|
||||
result = predict_trend([50], months_ahead=3)
|
||||
assert result["predicted"] == []
|
||||
assert result["confidence"] == 0.0
|
||||
|
||||
def test_predict_stable_trend(self):
|
||||
"""稳定趋势斜率应接近 0。"""
|
||||
result = predict_trend([70, 70, 70, 70], months_ahead=2)
|
||||
assert abs(result["slope"]) < 0.1
|
||||
|
||||
def test_predict_upward_trend(self):
|
||||
"""上升趋势斜率应为正。"""
|
||||
result = predict_trend([50, 55, 60, 65, 70], months_ahead=2)
|
||||
assert result["slope"] > 0
|
||||
|
||||
def test_predict_downward_trend(self):
|
||||
"""下降趋势斜率应为负。"""
|
||||
result = predict_trend([80, 75, 70, 65, 60], months_ahead=2)
|
||||
assert result["slope"] < 0
|
||||
|
||||
|
||||
class TestDetectAnomalies:
|
||||
"""异常检测函数测试。"""
|
||||
|
||||
def test_detect_with_normal_data(self):
|
||||
"""正常数据不应检测到异常。"""
|
||||
result = detect_anomalies([70, 71, 69, 70, 71])
|
||||
assert result == []
|
||||
|
||||
def test_detect_with_anomaly(self):
|
||||
"""包含异常值时应检测到。"""
|
||||
result = detect_anomalies([70, 71, 69, 70, 500], threshold=1.5)
|
||||
assert len(result) > 0
|
||||
assert 4 in result
|
||||
|
||||
def test_detect_with_insufficient_data(self):
|
||||
"""数据不足时应返回空。"""
|
||||
assert detect_anomalies([50, 60]) == []
|
||||
|
||||
def test_detect_with_constant_data(self):
|
||||
"""恒定数据不应检测到异常。"""
|
||||
assert detect_anomalies([70, 70, 70, 70]) == []
|
||||
|
||||
|
||||
class TestForecastEndpoint:
|
||||
"""预测接口测试。"""
|
||||
|
||||
def test_forecast_empty(self, client: TestClient, auth_headers: dict):
|
||||
"""无历史数据时应正常返回。"""
|
||||
resp = client.get("/api/v1/dashboard/forecasts", headers=auth_headers)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()["data"]
|
||||
assert "predictions" in data
|
||||
assert "trend_direction" in data
|
||||
assert "anomalies" in data
|
||||
|
||||
def test_forecast_with_company_id(self, client: TestClient, auth_headers: dict, company_id: str):
|
||||
"""指定企业 ID 应正常返回。"""
|
||||
resp = client.get(
|
||||
f"/api/v1/dashboard/forecasts?company_id={company_id}&months_ahead=3",
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_forecast_invalid_months(self, client: TestClient, auth_headers: dict):
|
||||
"""无效 months_ahead 应返回 422。"""
|
||||
resp = client.get("/api/v1/dashboard/forecasts?months_ahead=0", headers=auth_headers)
|
||||
assert resp.status_code == 422
|
||||
|
||||
def test_forecast_no_auth(self, client: TestClient):
|
||||
"""未认证应返回 401。"""
|
||||
resp = client.get("/api/v1/dashboard/forecasts")
|
||||
assert resp.status_code == 401
|
||||
Reference in New Issue
Block a user