gendesign/backend/tests/api/v1/conftest.py
bot-backend 12e2a9949d
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 12s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m9s
CI / backend-tests (pull_request) Successful in 6m46s
perf(tests): заглушить форсайт-enqueue в analyze-тестах Site Finder
analyze_parcel() в конце безусловно дёргает
forecast_site_finder_report.delay(...) (best-effort §22-форсайт, обёрнут
в try/except). В тестовой песочнице Celery-брокер (Redis) недоступен,
и .delay() синхронно ждёт kombu reconnect-backoff (~69с) прежде чем
исключение будет проглочено — эта пауза сидела внутри КАЖДОГО теста,
дёргающего POST /analyze без мока форсайт-таски (9 файлов
tests/api/v1/test_analyze_*.py, test_2464*.py — 32 теста, ~2218 из
2503с полного прогона).

Добавлена autouse-фикстура в tests/api/v1/conftest.py по образцу уже
существующей _stub_zone_regulation_resolver — глушит .delay в no-op
MagicMock для всех тестов каталога. Тесты самого enqueue
(test_parcels_forecast.py, test_run_history_and_response_contract.py)
переопределяют тот же target своим per-test patch поверх авто-фикстуры
(nested mock-scope), их проверки не затронуты.

Проверено: 7 целевых файлов (32 теста) — 36.7с суммарно вместо
таймаутов по 90с на файл, все зелёные.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG
2026-09-12 16:53:09 +03:00

61 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Общие фикстуры для api/v1 analyze-тестов.
PR-A (#1891) сделал geoportal зон-резолвер (``get_or_fetch_zone_regulation``)
БЕЗУСЛОВНЫМ в ``analyze_parcel`` — раньше он был gated за наличием dump-зоны
(``_nspd_zoning is not None``), теперь вызывается для любого ЕКБ-участка с centroid.
Analyze-тесты с ПОЗИЦИОННЫМ DB-моком (``_make_db_for_analyze`` + ``call_idx``/
``responses[...]``) НЕ мокали резолвер (до PR-A он не вызывался). Новый безусловный
вызов добавляет ``db.execute`` (get_cached) → сдвигает последовательность ответов
мока → последующие запросы (напр. ``parcel_meta``) получают чужой/пустой ответ и
становятся ``None``. Локально проходило (резолвер мог не разрезолвить точку), в CI
падало (``test_parcel_meta_found_in_cad_parcels``).
Авто-фикстура по умолчанию глушит резолвер в no-op (``return None``) для ВСЕХ тестов
в этом каталоге → блок 9e-bis ничего не синтезирует и не трогает БД (поведение
идентично до-PR-A). Тесты, которые проверяют САМ резолвер
(``test_analyze_zoning_regulation.py``), переопределяют этот же target своим
per-test ``patch`` — он применяется ПОВЕРХ авто-фикстуры (вложенный mock-scope), так
что их ожидаемые значения резолвера сохраняются.
Perf-fix (2026-09-12): в конце ``analyze_parcel`` — безусловный best-effort
``forecast_site_finder_report.delay(...)`` (§22-форсайт enqueue, см. app/api/v1/parcels.py).
В песочнице тестов Celery-брокер (Redis) недоступен → ``.delay()`` синхронно ждёт
kombu-реконнект с растущим backoff (~69с) ДО того как try/except его проглотит —
эта пауза оказалась внутри КАЖДОГО теста, который дергает ``POST /analyze`` и не
мокал форсайт-таску. Авто-фикстура ниже глушит ``.delay`` в no-op-мок для ВСЕХ
тестов каталога (как и с резолвером выше) — тесты самого enqueue
(``test_parcels_forecast.py``, ``test_run_history_and_response_contract.py``)
переопределяют тот же target своим per-test ``patch`` поверх авто-фикстуры.
"""
from __future__ import annotations
from collections.abc import Iterator
from unittest.mock import MagicMock, patch
import pytest
@pytest.fixture(autouse=True)
def _stub_zone_regulation_resolver() -> Iterator[None]:
"""No-op geoportal зон-резолвер по умолчанию (без сети, без desync DB-мока).
``return None`` → ``analyze`` не синтезирует ``nspd_zoning`` и не делает лишних
``db.execute``. Тесты резолвера переопределяют ``get_or_fetch_zone_regulation``
своим ``patch`` per-test.
"""
with patch("app.api.v1.parcels.get_or_fetch_zone_regulation", return_value=None):
yield
@pytest.fixture(autouse=True)
def _stub_forecast_enqueue() -> Iterator[None]:
"""No-op форсайт-enqueue по умолчанию (без реального Celery/Redis round-trip).
``.delay(...)`` в проде — fire-and-forget (best-effort, обёрнут в try/except в
``analyze_parcel``), тестам сам форсайт не нужен, а живой брокер в CI/локальной
песочнице недоступен и держит запрос ~69с на реконнект-backoff.
"""
with patch("app.workers.tasks.forecast.forecast_site_finder_report.delay", MagicMock()):
yield