83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
"""测试夹具:每个测试用独立的临时 SQLite 库。"""
|
|
import os
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
# 必须在导入 app 之前设置环境变量(config 是模块级单例)
|
|
_tmpdir = tempfile.mkdtemp(prefix="item-bank-test-")
|
|
os.environ["DATABASE_URL"] = f"sqlite+aiosqlite:///{_tmpdir}/test.db"
|
|
os.environ["DEBUG"] = "false"
|
|
os.environ["RATE_LIMIT_ENABLED"] = "false" # 默认关掉,限流测试里单独开
|
|
# 需满足 config.check_production_secrets 的要求(≥32 字节、非默认值)
|
|
os.environ["JWT_SECRET"] = "test-secret-long-enough-for-hs256-abcdefghij"
|
|
|
|
import pytest # noqa: E402
|
|
import pytest_asyncio # noqa: E402
|
|
from cryptography.fernet import Fernet # noqa: E402
|
|
from httpx import ASGITransport, AsyncClient # noqa: E402
|
|
|
|
# 生成合法的 Fernet key 并在导入 app 前写入
|
|
os.environ["FERNET_KEY"] = Fernet.generate_key().decode()
|
|
|
|
import app.models # noqa: E402,F401 注册所有模型
|
|
from app.db import Base, engine # noqa: E402
|
|
from app.main import app as fastapi_app # noqa: E402
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def db_schema():
|
|
"""每个测试前重建表,测试间互不干扰。"""
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.drop_all)
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
yield
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def client(db_schema):
|
|
transport = ASGITransport(app=fastapi_app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as c:
|
|
yield c
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def auth_headers(client):
|
|
"""注册并登录一个用户,返回可直接用的鉴权头。"""
|
|
|
|
async def _make(username: str = "alice", password: str = "secret123") -> dict:
|
|
await client.post(
|
|
"/api/auth/register", json={"username": username, "password": password}
|
|
)
|
|
resp = await client.post(
|
|
"/api/auth/login", data={"username": username, "password": password}
|
|
)
|
|
token = resp.json()["access_token"]
|
|
return {"Authorization": f"Bearer {token}"}
|
|
|
|
return _make
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def configure_ai(client):
|
|
"""给某个用户配好 AI 接口(api_key 会被加密存储)。"""
|
|
|
|
async def _make(headers: dict, api_key: str = "sk-test-value") -> dict:
|
|
resp = await client.put(
|
|
"/api/settings",
|
|
json={
|
|
"llm_base_url": "http://fake-llm",
|
|
"llm_text_model": "text-model",
|
|
"llm_vision_model": "vision-model",
|
|
"api_key": api_key,
|
|
},
|
|
headers=headers,
|
|
)
|
|
assert resp.status_code == 200
|
|
return resp.json()
|
|
|
|
return _make
|
|
|
|
|
|
def pytest_configure(config):
|
|
config.addinivalue_line("markers", "asyncio: async test")
|