- pytest_collection_modifyitems: skip @pytest.mark.network unless PROXYPOOL_RUN_NETWORK_TESTS=1 - Document opt-in in tests/README.md - e2e: replace removed crawl_timeout with validation_timeout Made-with: Cursor
4.7 KiB
4.7 KiB
测试说明
测试结构
tests/
├── conftest.py # pytest 配置和 fixtures
├── task_utils.py # 异步任务轮询(集成/E2E 共用)
├── support/ # 测试专用插件类等(非 mock)
├── README.md # 本文件
├── unit/ # 单元测试
│ ├── test_models.py # 模型测试
│ └── test_repositories.py # 仓库层测试
├── integration/ # 集成测试
│ ├── test_proxies_api.py # 代理 API 测试
│ ├── test_plugins_api.py # 插件 API 测试
│ ├── test_plugins_live_crawl.py # 各插件真实爬取验收(须外网)
│ ├── test_scheduler_api.py # 调度器 API 测试
│ ├── test_settings_api.py # 设置 API 测试
│ └── test_health_api.py # 健康检查测试
└── e2e/ # 端到端测试
└── test_full_workflow.py # 完整工作流测试
网络与真实调用
带 @pytest.mark.network 的用例会发起真实 HTTP 爬取,默认不运行(避免全量 pytest 卡住数十分种)。
需要跑外网验收时(PowerShell 示例):
$env:PROXYPOOL_RUN_NETWORK_TESTS="1"; pytest tests/integration/test_plugins_live_crawl.py -v --tb=short
离线快速检查直接:
pytest
插件爬取验收(test_plugins_live_crawl.py):
- 核心 8 插件:必须至少 1 条代理且无 Runner 失败(依赖稳定外网)。
fpw_*:允许部分源 0 条;单插件可能接近各插件crawl_timeout_seconds上限。
运行测试
安装测试依赖
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