"""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