test(tradein/admin): перенацелить patch-таргеты на kit + DI-guard asserts (#2397 slice A)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 7s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m37s
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 7s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m37s
После миграции admin.py на scraper_kit.orchestration.pipeline (предыдущий коммит) 4 endpoint-теста продолжали патчить устаревший app.services.scrape_pipeline.run_* — имя, на которое admin.py больше не ссылается. Мок не перехватывал вызов → FastAPI BackgroundTask реально запускал kit-sweep (сетевой I/O), что локально (без :5432) тихо падало на подключении к БД и глоталось except'ом, а на CI грозило зависанием/таймаутом. Перенацелены patch-таргеты на app.api.v1.admin.run_* (namespace, куда забинжен kit-импорт): - test_city_sweep.py::test_start_endpoint_ok -> run_avito_city_sweep - test_cian_city_sweep.py::test_cian_start_endpoint_ok -> run_cian_city_sweep - test_yandex_city_sweep.py::test_yandex_start_endpoint_ok -> run_yandex_city_sweep - test_sweep_imv_phase.py::test_sweep_endpoint_passes_enrich_imv -> run_avito_city_sweep Добавлены DI-guard assertions (закрывают coverage-gap: раньше проверялся только HTTP 200, не факт вызова kit с правильным DI) — mock_sweep.call_args.kwargs проверяется на RealScraperConfig/RealMatcherAdapter/RealEnrichmentJobs (там, где kit-сигнатура их требует) + наличие proxy_provider.
This commit is contained in:
parent
42b1ca6d7f
commit
d0b011d388
4 changed files with 62 additions and 9 deletions
|
|
@ -717,12 +717,14 @@ def test_cian_start_endpoint_validates_delay_too_low(app_with_admin) -> None:
|
|||
|
||||
|
||||
def test_cian_start_endpoint_ok(app_with_admin) -> None:
|
||||
"""Valid request → 200, run_id в ответе."""
|
||||
"""Valid request → 200, run_id; kit sweep вызван с DI (config/matcher, БЕЗ enrichment)."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from app.services.scraper_adapters import RealMatcherAdapter, RealScraperConfig
|
||||
|
||||
with (
|
||||
patch("app.services.scrape_runs.create_run", return_value=42),
|
||||
patch("app.services.scrape_pipeline.run_cian_city_sweep", new_callable=AsyncMock),
|
||||
patch("app.api.v1.admin.run_cian_city_sweep", new_callable=AsyncMock) as mock_sweep,
|
||||
):
|
||||
r = app_with_admin.post(
|
||||
"/api/v1/admin/scrape/cian-city-sweep",
|
||||
|
|
@ -735,6 +737,13 @@ def test_cian_start_endpoint_ok(app_with_admin) -> None:
|
|||
assert body["pages_per_anchor"] == 2
|
||||
assert body["detail_top_n"] == 5
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
kw = mock_sweep.call_args.kwargs
|
||||
assert isinstance(kw["config"], RealScraperConfig)
|
||||
assert isinstance(kw["matcher"], RealMatcherAdapter)
|
||||
assert "proxy_provider" in kw
|
||||
assert "enrichment" not in kw
|
||||
|
||||
|
||||
def test_cian_cancel_endpoint(app_with_admin) -> None:
|
||||
"""Cancel endpoint возвращает run_id + cancelled=True."""
|
||||
|
|
|
|||
|
|
@ -313,11 +313,17 @@ def test_start_endpoint_validates_request_delay_too_low(app_with_admin) -> None:
|
|||
|
||||
|
||||
def test_start_endpoint_ok(app_with_admin) -> None:
|
||||
"""Valid request → 200, run_id в ответе."""
|
||||
"""Valid request → 200, run_id в ответе; kit sweep вызван с DI (config/matcher/enrichment)."""
|
||||
from app.services.scraper_adapters import (
|
||||
RealEnrichmentJobs,
|
||||
RealMatcherAdapter,
|
||||
RealScraperConfig,
|
||||
)
|
||||
|
||||
with (
|
||||
patch("app.api.v1.admin.has_running_run", return_value=False),
|
||||
patch("app.services.scrape_runs.create_run", return_value=7),
|
||||
patch("app.services.scrape_pipeline.run_avito_city_sweep", new_callable=AsyncMock),
|
||||
patch("app.api.v1.admin.run_avito_city_sweep", new_callable=AsyncMock) as mock_sweep,
|
||||
):
|
||||
r = app_with_admin.post(
|
||||
"/api/v1/admin/scrape/avito-city-sweep",
|
||||
|
|
@ -329,6 +335,13 @@ def test_start_endpoint_ok(app_with_admin) -> None:
|
|||
assert body["status"] == "running"
|
||||
assert body["pages_per_anchor"] == 2
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
kw = mock_sweep.call_args.kwargs
|
||||
assert isinstance(kw["config"], RealScraperConfig)
|
||||
assert isinstance(kw["matcher"], RealMatcherAdapter)
|
||||
assert isinstance(kw["enrichment"], RealEnrichmentJobs)
|
||||
assert "proxy_provider" in kw
|
||||
|
||||
|
||||
def test_cancel_endpoint_exists(app_with_admin) -> None:
|
||||
"""Cancel endpoint returns run_id + cancelled flag."""
|
||||
|
|
|
|||
|
|
@ -453,14 +453,24 @@ def test_city_sweep_start_request_enrich_imv_false() -> None:
|
|||
|
||||
|
||||
def test_sweep_endpoint_passes_enrich_imv(app_with_admin) -> None:
|
||||
"""POST /scrape/avito-city-sweep с enrich_imv=False → sweep вызывается без IMV."""
|
||||
"""POST /scrape/avito-city-sweep с enrich_imv=False → sweep вызывается без IMV.
|
||||
|
||||
kit sweep вызван с DI (config/matcher/enrichment) — mock должен перехватывать
|
||||
имя, забинженное в app.api.v1.admin (kit-импорт), не устаревший scrape_pipeline.
|
||||
"""
|
||||
from app.services.scraper_adapters import (
|
||||
RealEnrichmentJobs,
|
||||
RealMatcherAdapter,
|
||||
RealScraperConfig,
|
||||
)
|
||||
|
||||
with (
|
||||
patch("app.api.v1.admin.has_running_run", return_value=False),
|
||||
patch("app.services.scrape_runs.create_run", return_value=42),
|
||||
patch(
|
||||
"app.services.scrape_pipeline.run_avito_city_sweep",
|
||||
"app.api.v1.admin.run_avito_city_sweep",
|
||||
new_callable=AsyncMock,
|
||||
),
|
||||
) as mock_sweep,
|
||||
):
|
||||
r = app_with_admin.post(
|
||||
"/api/v1/admin/scrape/avito-city-sweep",
|
||||
|
|
@ -470,6 +480,14 @@ def test_sweep_endpoint_passes_enrich_imv(app_with_admin) -> None:
|
|||
body = r.json()
|
||||
assert body["run_id"] == 42
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
kw = mock_sweep.call_args.kwargs
|
||||
assert isinstance(kw["config"], RealScraperConfig)
|
||||
assert isinstance(kw["matcher"], RealMatcherAdapter)
|
||||
assert isinstance(kw["enrichment"], RealEnrichmentJobs)
|
||||
assert "proxy_provider" in kw
|
||||
assert kw["enrich_imv"] is False
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app_with_admin():
|
||||
|
|
|
|||
|
|
@ -623,12 +623,18 @@ def test_yandex_start_endpoint_validates_delay_too_low(app_with_admin) -> None:
|
|||
|
||||
|
||||
def test_yandex_start_endpoint_ok(app_with_admin) -> None:
|
||||
"""Valid request → 200, run_id в ответе."""
|
||||
"""Valid request → 200, run_id в ответе; kit sweep вызван с DI (config/matcher/enrichment)."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.services.scraper_adapters import (
|
||||
RealEnrichmentJobs,
|
||||
RealMatcherAdapter,
|
||||
RealScraperConfig,
|
||||
)
|
||||
|
||||
with (
|
||||
patch("app.services.scrape_runs.create_run", return_value=55),
|
||||
patch("app.services.scrape_pipeline.run_yandex_city_sweep", new_callable=AsyncMock),
|
||||
patch("app.api.v1.admin.run_yandex_city_sweep", new_callable=AsyncMock) as mock_sweep,
|
||||
):
|
||||
r = app_with_admin.post(
|
||||
"/api/v1/admin/scrape/yandex-city-sweep",
|
||||
|
|
@ -641,6 +647,13 @@ def test_yandex_start_endpoint_ok(app_with_admin) -> None:
|
|||
assert body["pages_per_anchor"] == 2
|
||||
assert body["detail_top_n"] == 0
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
kw = mock_sweep.call_args.kwargs
|
||||
assert isinstance(kw["config"], RealScraperConfig)
|
||||
assert isinstance(kw["matcher"], RealMatcherAdapter)
|
||||
assert isinstance(kw["enrichment"], RealEnrichmentJobs)
|
||||
assert "proxy_provider" in kw
|
||||
|
||||
|
||||
def test_yandex_cancel_endpoint(app_with_admin) -> None:
|
||||
"""Cancel endpoint возвращает run_id + cancelled=True."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue