Files
projectAIpopular/tests/test_gateway.py
T

126 lines
3.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.
"""FastAPI 网关测试:v1 legacy 端点保持 + v2 端点(封闭,注入 mock 管线)。"""
import pytest
pytest.importorskip("fastapi")
pytest.importorskip("httpx")
from fastapi.testclient import TestClient
import gateway.api as ga
from gateway.api import app
@pytest.fixture()
def client():
return TestClient(app)
@pytest.fixture()
def v2_client(client):
# 用 mock worker 构建真实 v2 管线并注入(无需 API key / 真实模型)
pipe = ga.build_v2_pipeline(worker_cfg_override={"backend": "mock"})
ga.set_pipeline(pipe)
return client
def test_health(client):
resp = client.get("/health")
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "ok"
assert "code" in data["domains"]
def test_chat_legacy(client):
resp = client.post("/chat/legacy", json={"query": "用 Python 写一个快速排序函数"})
assert resp.status_code == 200
data = resp.json()
assert data["response"]
assert data["domain"] == "code"
assert "route" in data
def test_chat_v2(v2_client):
# POST /chat 立即返回 request_id(异步协议)
resp = v2_client.post("/chat", json={"query": "请介绍快速排序算法"})
assert resp.status_code == 200
data = resp.json()
assert "request_id" in data
assert data["status"] == "pending"
# 轮询 /runs/{id}/status 直到完成
import time
for _ in range(50): # 最多 5s
time.sleep(0.1)
status_resp = v2_client.get(f"/runs/{data['request_id']}/status")
assert status_resp.status_code == 200
s = status_resp.json()
if s["status"] in ("done", "failed"):
break
assert s["status"] == "done", f"期望 done,实际 {s['status']}error={s.get('error')}"
assert s["response"]
assert "pipeline_status" in s
assert s["pipeline_status"] in ("fast_path", "done", "escalated")
# fast_path 不写 workspace.json,所以 workspace_path 可能为 None
if s["pipeline_status"] != "fast_path":
assert s["workspace_path"] is not None
def test_chat_empty_query(client):
resp = client.post("/chat", json={"query": ""})
assert resp.status_code == 422
def test_metrics(client):
resp = client.get("/metrics")
assert resp.status_code == 200
data = resp.json()
assert "router" in data
assert "cache" in data
assert "v2" in data
assert "review" in data
def test_config_get_put_reset(client):
# GET 默认
r = client.get("/config")
assert r.status_code == 200
assert r.json()["worker"]["backend"] in ("llama_server", "openai", "mock")
# PUT 更新 worker
r2 = client.put("/config", json={"worker": {"backend": "mock", "temperature": 0.5}})
assert r2.status_code == 200
assert r2.json()["worker"]["temperature"] == 0.5
# 重置
r3 = client.post("/config/reset")
assert r3.status_code == 200
assert r3.json()["worker"]["backend"] == "llama_server"
def test_workspace_not_found(client):
resp = client.get("/runs/nonexistent/workspace")
assert resp.status_code == 404
def test_web_ui_served(client):
resp = client.get("/")
assert resp.status_code == 200
assert resp.headers["content-type"].startswith("text/html")
# Vue SPA:由 Vite 生成,特征是 <div id="app"> 和 /static/assets/ 引用
assert '<div id="app">' in resp.text
assert '/static/assets/' in resp.text
def test_review_flow(client):
q = ga.get_review()
rid = q.enqueue("req-x", "q", "ans", tags=["safety"], reason="test")
assert q.count() >= 1
resp = client.get("/review/queue")
assert resp.status_code == 200
resp2 = client.post(f"/review/{rid}", params={"verdict": "approve"})
assert resp2.status_code == 200
assert resp2.json()["ok"] is True