gendesign/tradein-mvp/backend/tests/test_3051_dkp_import_moscow.py
bot-backend beb487c12e
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
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 5m2s
test(#3051): тесты трека «Москва» — импорт ДКП по 77, per-source чекпоинт, wildcard-хендлер, регион-скоуп ДКП-коридора, миграция 289, валидация deploy-скрипта
Тесты пишутся ПОСЛЕ живой проверки функционала (правило от 08.09):
импорт по 77 — run 6460 (212 937 строк), регион-фильтр коридора — smoke
до/после импорта. 14 тестов: SQL-текст через inspect (regex \s+ для
многострочных клозов), чистые функции, мок db по образцу 2846, subprocess
bash с урезанным PATH (падение от валидации, не от отсутствия docker).
2026-09-09 02:23:47 +03:00

93 lines
4.2 KiB
Python
Raw Permalink 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.

"""#3051 п.3 — параметризация import_rosreestr_dkp по региону (Москва, region_code=77).
Чисто-юнит: ассертим SQL-текст, эмитируемый import_rosreestr_dkp (через
inspect.getsource), тем же механизмом, что и test_rosreestr_dedup_key.py — без живого
FDW / DB-фикстуры. Многострочные клозы матчатся regex с `\\s+`, а не подстрокой: SQL
внутри text(...) переносится по строкам, точный пробельный рисунок хрупок.
"""
from __future__ import annotations
import inspect
import os
import re
from pathlib import Path
from unittest.mock import MagicMock
# Импорт app.services.scheduler тянет app.core.config.Settings → требует DATABASE_URL.
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")
import pytest
from app.services import scheduler
_SQL_DIR = Path(__file__).resolve().parents[1] / "data" / "sql"
_MIGRATION_289 = _SQL_DIR / "289_rosreestr_fdw_msk_columns_seed77.sql"
_IMPORT_SRC = inspect.getsource(scheduler.import_rosreestr_dkp)
def test_case_on_canonical_city_bind() -> None:
"""canonical_city — bind-параметр CASE-выражения (address/city/raw_payload),
не Python if/else на конкретный код региона (#3051: одна ветка SQL решает и
для 66 (None), и для 77 ('Москва'), и для любого будущего региона).
"""
assert _IMPORT_SRC.count("CAST(:canonical_city AS text) IS NOT NULL") >= 3
assert '"canonical_city": region.canonical_city' in _IMPORT_SRC
def test_city_filter_bypassed_only_with_canonical_city() -> None:
"""WHERE-клоз: у региона С canonical_city city IS NOT NULL НЕ применяется —
иначе для Москвы теряется ~10% строк с пустым city источника (округ/поселение
не всегда заполнен).
"""
pattern = re.compile(
r"\(\s*CAST\(:canonical_city AS text\) IS NOT NULL\s*"
r"OR \(city IS NOT NULL AND trim\(city\) <> ''\)\s*\)"
)
assert pattern.search(_IMPORT_SRC), "не найден WHERE-клоз city IS NOT NULL bypass"
def test_raw_payload_jsonb_bind() -> None:
"""raw_payload (jsonb) — исходные city/okato/quarter_cad_number/district для
регионов с canonical_city; bind через CAST(... AS jsonb), не литерал.
"""
assert "CAST(:raw_payload AS jsonb)" in _IMPORT_SRC
assert "raw_payload = EXCLUDED.raw_payload" in _IMPORT_SRC
assert "IS DISTINCT FROM EXCLUDED.raw_payload" in _IMPORT_SRC
assert "json.dumps" in _IMPORT_SRC
def test_doc_types_param_default_dkp() -> None:
"""doc_types — параметр (было: литерал 'ДКП'), дефолт ['ДКП'] сохраняет прежнее
поведение (только вторичка).
"""
assert "ANY(CAST(:doc_types AS text[]))" in _IMPORT_SRC
assert 'params.get("doc_types") or ["ДКП"]' in _IMPORT_SRC
def test_unknown_region_raises() -> None:
"""region_code без записи в REGIONS → ValueError ДО любого db.execute — прогон
не должен успеть тронуть БД с неизвестным региональным контекстом.
"""
db = MagicMock()
with pytest.raises(ValueError, match="99"):
scheduler.import_rosreestr_dkp(db, run_id=1, params={"region_code": 99})
db.execute.assert_not_called()
def test_dkp_source_for_region() -> None:
"""66 → байт-в-байт прежнее имя _DKP_SOURCE; 77 → суффиксное имя, совпадающее
с source seed-строки миграции 289 (изоляция чекпоинтов между регионами).
"""
assert scheduler._dkp_source_for_region(66) == scheduler._DKP_SOURCE
assert scheduler._dkp_source_for_region(77) == "rosreestr_dkp_import_77"
sql = _MIGRATION_289.read_text("utf-8")
assert "'rosreestr_dkp_import_77'" in sql, "seed-source миграции 289 разъехался с кодом"