- 删除 ValidationQueue 双轨持久化队列,替换为纯内存 AsyncWorkerPool - 引入统一后台任务框架 JobExecutor(Job/CrawlJob/ValidateAllJob) - 新增 PluginRunner 统一插件执行(超时、重试、健康检查、统计) - 重构 SchedulerService 职责收敛为仅定时触发 ValidateAllJob - 使用 AsyncExitStack 重构 lifespan,安全管理长生命周期资源 - 路由层瘦身 50%+,业务异常上抛由全局中间件统一处理 - 实现设置全热更新(WorkerPool 并发、Validator 超时即时生效) - 前端 Store 强制写后重新拉取,消除乐观更新数据不同步 - 删除 queue.py / task_repo.py / task_service.py - 新增 execution 单元测试,全部 85 个测试通过
测试说明
测试结构
tests/
├── conftest.py # pytest 配置和 fixtures
├── README.md # 本文件
├── unit/ # 单元测试
│ ├── test_models.py # 模型测试
│ └── test_repositories.py # 仓库层测试
├── integration/ # 集成测试
│ ├── test_proxies_api.py # 代理 API 测试
│ ├── test_plugins_api.py # 插件 API 测试
│ ├── test_scheduler_api.py # 调度器 API 测试
│ ├── test_settings_api.py # 设置 API 测试
│ └── test_health_api.py # 健康检查测试
└── e2e/ # 端到端测试
└── test_full_workflow.py # 完整工作流测试
运行测试
安装测试依赖
pip install pytest pytest-asyncio httpx
运行所有测试
pytest
运行特定类型的测试
# 仅运行单元测试
pytest tests/unit -v
# 仅运行集成测试
pytest tests/integration -v
# 仅运行 E2E 测试
pytest tests/e2e -v
运行特定测试文件
pytest tests/integration/test_proxies_api.py -v
运行特定测试函数
pytest tests/integration/test_proxies_api.py::TestProxiesAPI::test_get_stats -v
测试覆盖的 API
代理 API (/api/proxies/*)
- ✅
GET /api/proxies/stats- 获取统计信息 - ✅
POST /api/proxies- 列出代理 - ✅
GET /api/proxies/random- 获取随机代理 - ✅
GET /api/proxies/export/{format}- 导出代理 (csv, txt, json) - ✅
DELETE /api/proxies/{ip}/{port}- 删除代理 - ✅
POST /api/proxies/batch-delete- 批量删除 - ✅
DELETE /api/proxies/clean-invalid- 清理无效代理
插件 API (/api/plugins/*)
- ✅
GET /api/plugins- 列出插件 - ✅
PUT /api/plugins/{id}/toggle- 切换插件状态 - ✅
GET /api/plugins/{id}/config- 获取插件配置 - ✅
POST /api/plugins/{id}/config- 更新插件配置 - ✅
POST /api/plugins/{id}/crawl- 触发单个插件爬取 - ✅
POST /api/plugins/crawl-all- 触发所有插件爬取
调度器 API (/api/scheduler/*)
- ✅
GET /api/scheduler/status- 获取调度器状态 - ✅
POST /api/scheduler/start- 启动调度器 - ✅
POST /api/scheduler/stop- 停止调度器 - ✅
POST /api/scheduler/validate-now- 立即验证
设置 API (/api/settings)
- ✅
GET /api/settings- 获取设置 - ✅
POST /api/settings- 保存设置
健康检查
- ✅
GET /- 根端点 - ✅
GET /health- 健康检查
测试 Fixtures
client
异步 HTTP 客户端,用于发送请求到测试应用。
async def test_example(client):
response = await client.get("/api/proxies/stats")
assert response.status_code == 200
db
数据库连接 fixture。
async def test_example(db, proxy_repo):
await proxy_repo.insert_or_update(db, "192.168.1.1", 8080, "http", 50)
sample_proxy
创建一个测试代理并自动清理。
async def test_example(client, sample_proxy):
# sample_proxy = {"ip": "192.168.1.1", "port": 8080, "protocol": "http", "score": 50}
response = await client.delete(f"/api/proxies/{sample_proxy['ip']}/{sample_proxy['port']}")
assert response.status_code == 200
编写新测试
单元测试示例
# tests/unit/test_new_feature.py
import pytest
from app.models.domain import ProxyRaw
class TestProxyRaw:
def test_create(self):
proxy = ProxyRaw("192.168.1.1", 8080, "http")
assert proxy.ip == "192.168.1.1"
集成测试示例
# tests/integration/test_new_api.py
import pytest
class TestNewAPI:
@pytest.mark.asyncio
async def test_new_endpoint(self, client):
response = await client.get("/api/new-endpoint")
assert response.status_code == 200