Files
ProxyPool/tests/unit/test_models.py
祀梦 0131c8b408 feat: fpw plugins, validation/crawl perf, WS stats, test DB isolation
- Add Free_Proxy_Website-style fpw_* plugins and register them
- Per-plugin crawl timeout (crawl_timeout_seconds=120); remove global crawl_timeout setting
- Validator: fix connect vs total timeout on save; SOCKS session LRU cache; drop redundant semaphore
- Validation handler uses single DB connection; batch upsert after crawl; WorkerPool put_nowait
- Remove unused max_retries from settings API/UI; settings maintenance SQL + init_db cleanup of deprecated keys
- WebSocket dashboard stats; ProxyList pool_filter and API alignment
- POST /api/proxies/delete-one for IPv6-safe deletes; task poll stops on 404
- pytest uses PROXYPOOL_DB_PATH=db/proxies.test.sqlite so tests do not wipe production DB
- .gitignore: explicit proxies.test.sqlite patterns; fix plugin_service ValidationException import

Made-with: Cursor
2026-04-05 13:39:19 +08:00

151 lines
4.6 KiB
Python

"""模型单元测试"""
import pytest
from datetime import datetime
from app.models.domain import ProxyRaw, Proxy, PluginInfo
from app.models.schemas import (
ProxyCreate,
ProxyListRequest,
SettingsSchema,
BatchDeleteRequest,
)
class TestProxyRaw:
"""测试 ProxyRaw 领域模型"""
def test_create_proxy_raw(self):
"""测试创建原始代理"""
proxy = ProxyRaw("192.168.1.1", 8080, "http")
assert proxy.ip == "192.168.1.1"
assert proxy.port == 8080
assert proxy.protocol == "http"
def test_protocol_normalization(self):
"""测试协议标准化"""
proxy = ProxyRaw("192.168.1.1", 8080, "HTTP")
assert proxy.protocol == "http"
def test_invalid_protocol_defaults_to_http(self):
"""测试无效协议默认为 http"""
proxy = ProxyRaw("192.168.1.1", 8080, "invalid")
assert proxy.protocol == "http"
class TestProxy:
"""测试 Proxy 领域模型"""
def test_create_proxy(self):
"""测试创建代理实体"""
proxy = Proxy(
ip="192.168.1.1",
port=8080,
protocol="http",
score=50,
response_time_ms=100.5,
last_check=datetime.now(),
created_at=datetime.now(),
)
assert proxy.ip == "192.168.1.1"
assert proxy.score == 50
class TestPluginInfo:
"""测试 PluginInfo 领域模型"""
def test_create_plugin_info(self):
"""测试创建插件信息"""
plugin = PluginInfo(
id="test_plugin",
name="test_plugin",
display_name="测试插件",
description="用于测试",
enabled=True,
success_count=10,
failure_count=2,
)
assert plugin.id == "test_plugin"
assert plugin.enabled is True
assert plugin.success_count == 10
class TestProxyCreateSchema:
"""测试 ProxyCreate Pydantic 模型"""
def test_valid_proxy_create(self):
"""测试有效的代理创建"""
proxy = ProxyCreate(ip="192.168.1.1", port=8080, protocol="http")
assert proxy.ip == "192.168.1.1"
assert proxy.port == 8080
def test_port_validation(self):
"""测试端口验证"""
with pytest.raises(Exception):
ProxyCreate(ip="192.168.1.1", port=70000) # 超出范围
def test_protocol_validation(self):
"""测试协议验证"""
with pytest.raises(Exception):
ProxyCreate(ip="192.168.1.1", port=8080, protocol="invalid")
class TestProxyListRequest:
"""测试 ProxyListRequest 模式"""
def test_default_values(self):
"""测试默认值"""
request = ProxyListRequest()
assert request.page == 1
assert request.page_size == 20
assert request.sort_by == "last_check"
assert request.sort_order == "DESC"
def test_custom_values(self):
"""测试自定义值"""
request = ProxyListRequest(page=2, page_size=50, protocol="https")
assert request.page == 2
assert request.page_size == 50
assert request.protocol == "https"
def test_pool_filter_pending_available(self):
r1 = ProxyListRequest(pool_filter="pending")
assert r1.pool_filter == "pending"
r2 = ProxyListRequest(pool_filter="all")
assert r2.pool_filter is None
with pytest.raises(Exception):
ProxyListRequest(pool_filter="invalid")
class TestSettingsSchema:
"""测试 SettingsSchema"""
def test_default_settings(self):
"""测试默认设置"""
settings = SettingsSchema()
assert settings.validation_timeout == 6
assert settings.default_concurrency == 120
assert settings.auto_validate is True
assert settings.auto_validate_after_crawl is False
def test_custom_settings(self):
"""测试自定义设置"""
settings = SettingsSchema(validation_timeout=25, auto_validate=False)
assert settings.validation_timeout == 25
assert settings.auto_validate is False
def test_settings_schema_ignores_unknown_fields(self):
s = SettingsSchema.model_validate({"validation_timeout": 10, "crawl_timeout": 99})
assert "crawl_timeout" not in s.model_dump()
assert s.validation_timeout == 10
class TestBatchDeleteRequest:
"""测试 BatchDeleteRequest"""
def test_valid_batch_delete(self):
"""测试有效的批量删除"""
request = BatchDeleteRequest(proxies=[
{"ip": "192.168.1.1", "port": 8080},
{"ip": "192.168.1.2", "port": 8081},
])
assert len(request.proxies) == 2