Files
ProxyPool/tests/integration/test_proxies_api.py
祀梦 38bd66128b 重构: 迁移后端代码到 app 目录,前端移动到 WebUI,添加完整测试套件
主要变更:
- 后端代码从根目录迁移到 app/ 目录
- 前端代码从 frontend/ 重命名为 WebUI/
- 更新所有导入路径以适配新结构
- 提取公共 API 响应函数到 app/api/common.py
- 精简验证器服务代码
- 更新启动脚本和文档

测试:
- 新增完整测试套件 (tests/)
- 单元测试: 模型、仓库层
- 集成测试: 覆盖所有 22+ API 端点
- E2E 测试: 4个完整工作流场景
- 添加 pytest 配置和测试运行脚本
2026-04-04 13:32:36 +08:00

145 lines
5.5 KiB
Python

"""代理 API 集成测试 - 测试 /api/proxies/* 所有接口"""
import pytest
class TestProxiesAPI:
"""测试代理相关 API"""
@pytest.mark.asyncio
async def test_get_stats(self, client):
"""测试 GET /api/proxies/stats"""
response = await client.get("/api/proxies/stats")
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
assert "data" in data
assert "total" in data["data"]
assert "available" in data["data"]
assert "scheduler_running" in data["data"]
@pytest.mark.asyncio
async def test_list_proxies(self, client):
"""测试 POST /api/proxies"""
request_data = {
"page": 1,
"page_size": 10,
"protocol": None,
"min_score": 0,
"sort_by": "last_check",
"sort_order": "DESC"
}
response = await client.post("/api/proxies", json=request_data)
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
assert "list" in data["data"]
assert "total" in data["data"]
assert "page" in data["data"]
@pytest.mark.asyncio
async def test_list_proxies_with_protocol_filter(self, client):
"""测试 POST /api/proxies 带协议过滤"""
request_data = {
"page": 1,
"page_size": 10,
"protocol": "http",
"min_score": 0,
}
response = await client.post("/api/proxies", json=request_data)
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
@pytest.mark.asyncio
async def test_list_proxies_invalid_protocol(self, client):
"""测试 POST /api/proxies 无效协议"""
request_data = {
"page": 1,
"page_size": 10,
"protocol": "invalid",
}
response = await client.post("/api/proxies", json=request_data)
assert response.status_code == 422 # 验证错误
@pytest.mark.asyncio
async def test_get_random_proxy_empty(self, client):
"""测试 GET /api/proxies/random - 空数据库"""
response = await client.get("/api/proxies/random")
# 可能返回 200(有数据) 或 404(无数据)
assert response.status_code in [200, 404]
@pytest.mark.asyncio
async def test_delete_proxy(self, client, sample_proxy):
"""测试 DELETE /api/proxies/{ip}/{port}"""
response = await client.delete(f"/api/proxies/{sample_proxy['ip']}/{sample_proxy['port']}")
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
@pytest.mark.asyncio
async def test_delete_nonexistent_proxy(self, client):
"""测试 DELETE /api/proxies/{ip}/{port} - 不存在的代理"""
response = await client.delete("/api/proxies/999.999.999.999/99999")
# 即使代理不存在也返回成功(幂等删除)
assert response.status_code == 200
@pytest.mark.asyncio
async def test_batch_delete_proxies(self, client):
"""测试 POST /api/proxies/batch-delete"""
request_data = {
"proxies": [
{"ip": "192.168.1.1", "port": 8080},
{"ip": "192.168.1.2", "port": 8081},
]
}
response = await client.post("/api/proxies/batch-delete", json=request_data)
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
assert "deleted_count" in data["data"]
@pytest.mark.asyncio
async def test_batch_delete_too_many(self, client):
"""测试 POST /api/proxies/batch-delete - 超过限制"""
request_data = {
"proxies": [{"ip": f"192.168.1.{i}", "port": 8080} for i in range(1001)]
}
response = await client.post("/api/proxies/batch-delete", json=request_data)
assert response.status_code == 422 # 验证错误
@pytest.mark.asyncio
async def test_clean_invalid_proxies(self, client):
"""测试 DELETE /api/proxies/clean-invalid"""
response = await client.delete("/api/proxies/clean-invalid")
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
assert "deleted_count" in data["data"]
@pytest.mark.asyncio
async def test_export_proxies_csv(self, client):
"""测试 GET /api/proxies/export/csv"""
response = await client.get("/api/proxies/export/csv")
assert response.status_code == 200
assert response.headers["content-type"] == "text/csv"
@pytest.mark.asyncio
async def test_export_proxies_txt(self, client):
"""测试 GET /api/proxies/export/txt"""
response = await client.get("/api/proxies/export/txt")
assert response.status_code == 200
assert response.headers["content-type"] == "text/plain"
@pytest.mark.asyncio
async def test_export_proxies_json(self, client):
"""测试 GET /api/proxies/export/json"""
response = await client.get("/api/proxies/export/json")
assert response.status_code == 200
assert response.headers["content-type"] == "application/json"
@pytest.mark.asyncio
async def test_export_proxies_invalid_format(self, client):
"""测试 GET /api/proxies/export/invalid - 无效格式"""
response = await client.get("/api/proxies/export/invalid")
assert response.status_code == 400 # 错误响应