대시보드 실측 반영 — Decodo residential 은 포트 기반 sticky(gate:10001..N, 고정 user/pass, 각 포트=sticky 세션). IP 회전 = 포트 순환. - proxy.DecodoProxy: 시간창 기반 포트 선택(창 안 동일 IP, 창 지나면 다음 포트=새 IP). _UNSET sentinel 로 '미지정(env)' vs '명시적 빈값' 구분(테스트 결정성) - coupang/adapter: 이미지/미디어/폰트/CSS 차단(block_resources) — per-GB 대역폭 대폭 절감, Akamai(JS)·상품파싱엔 무영향. 라이브 검증: 차단 ON 에도 Akamai 통과+파싱 정상 - .env.example: DECODO_HOST/USERNAME/PASSWORD/PORT_START/PORT_END/SESSION_MINUTES - tests: 포트범위/시간창 안정성/활성조건 5건 → 전체 44/44 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""DECODO 프록시 제공자 테스트 (포트 기반 sticky, 순수·네트워크 불필요)."""
|
|
|
|
from services.search.proxy import DecodoProxy
|
|
|
|
|
|
def _p(**kw):
|
|
base = dict(host="gate.decodo.com", username="user1", password="pw", port_start=10001, port_end=10010, session_minutes=10)
|
|
base.update(kw)
|
|
return DecodoProxy(**base)
|
|
|
|
|
|
def test_disabled_when_credentials_missing():
|
|
assert DecodoProxy(host="", username="", password="", port_start=None, port_end=None).enabled is False
|
|
assert _p(password="").enabled is False
|
|
assert _p(port_end=None).enabled is False
|
|
assert _p().enabled is True
|
|
|
|
|
|
def test_playwright_proxy_shape():
|
|
cfg = _p().playwright_proxy()
|
|
assert cfg["username"] == "user1" and cfg["password"] == "pw" # 고정 자격증명
|
|
assert cfg["server"].startswith("http://gate.decodo.com:")
|
|
port = int(cfg["server"].rsplit(":", 1)[1])
|
|
assert 10001 <= port <= 10010 # 포트 범위 안
|
|
|
|
|
|
def test_disabled_returns_none():
|
|
assert DecodoProxy(host="", username="", password="", port_start=None, port_end=None).playwright_proxy() is None
|
|
|
|
|
|
def test_port_selected_within_range_and_stable_in_window():
|
|
p = _p()
|
|
port = p._port()
|
|
assert 10001 <= port <= 10010
|
|
assert p._port() == port # 같은 시간창에서는 동일 포트(동일 sticky IP)
|
|
|
|
|
|
def test_single_port_range():
|
|
p = _p(port_start=10001, port_end=10001)
|
|
assert p._port() == 10001 # 포트 1개면 항상 그 포트
|