test: 添加测试框架和全面的单元测试

- 添加 pytest 配置和测试依赖到 requirements.txt
- 创建测试包结构和 fixtures (conftest.py)
- 添加数据库模块的 CRUD 操作测试 (test_database.py)
- 添加 Provider 插件系统测试 (test_providers.py)
- 添加调度器模块测试 (test_scheduler.py)
- 添加 API 路由测试 (test_api.py)
- 添加回归测试覆盖边界条件和错误处理 (test_regressions.py)
- 添加健康检查端点用于容器监控
- 修复调度器中的日历计算逻辑和任务执行参数处理
- 更新数据库函数以返回操作结果状态
This commit is contained in:
congsh
2026-03-31 22:36:18 +08:00
parent 61ce809634
commit 37d282c0a2
17 changed files with 1769 additions and 50 deletions
+10 -5
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
import json
import time
from typing import Any
from fastapi import APIRouter, Header, HTTPException, Request
@@ -18,8 +17,8 @@ router = APIRouter()
def _verify_key(authorization: str | None):
expected = settings.server.proxy_api_key
if not expected or expected == "sk-plan-manage-change-me":
return # 未配置则跳过鉴权
if not expected:
return
if not authorization:
raise HTTPException(401, "Missing Authorization header")
token = authorization.removeprefix("Bearer ").strip()
@@ -150,13 +149,17 @@ async def anthropic_messages(
if not provider:
raise HTTPException(500, f"Provider '{plan['provider_name']}' not registered")
extra_kwargs = {k: v for k, v in body.items() if k not in ("model", "messages", "stream", "system")}
if stream:
async def anthropic_stream():
"""将 OpenAI SSE 格式转换为 Anthropic SSE 格式"""
yield f"event: message_start\ndata: {json.dumps({'type': 'message_start', 'message': {'id': 'msg_proxy', 'type': 'message', 'role': 'assistant', 'model': model, 'content': []}})}\n\n"
yield f"event: content_block_start\ndata: {json.dumps({'type': 'content_block_start', 'index': 0, 'content_block': {'type': 'text', 'text': ''}})}\n\n"
async for chunk_data in _stream_and_count(provider, oai_messages, model, plan, True):
async for chunk_data in _stream_and_count(
provider, oai_messages, model, plan, True, **extra_kwargs
):
if chunk_data.startswith("data: [DONE]"):
break
if chunk_data.startswith("data: "):
@@ -179,7 +182,9 @@ async def anthropic_messages(
)
else:
chunks = []
async for c in _stream_and_count(provider, oai_messages, model, plan, False):
async for c in _stream_and_count(
provider, oai_messages, model, plan, False, **extra_kwargs
):
chunks.append(c)
oai_resp = json.loads(chunks[0]) if chunks else {}
# OpenAI 响应 -> Anthropic 响应