gendesign/backend/tests/services/test_2464_docstring_matches_code.py
bot-backend cdf493f345
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy Trade-In / changes (push) Successful in 13s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy / build-backend (push) Successful in 2m23s
Deploy Trade-In / test (push) Successful in 3m56s
Deploy / build-worker (push) Successful in 4m16s
Deploy Trade-In / build-backend (push) Successful in 1m19s
Deploy / deploy (push) Successful in 1m49s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 12s
Deploy Trade-In / deploy (push) Successful in 2m25s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 11s
chore(format): нормализация под ruff 0.15.20 — 161 файл, только формат (#2864) (#3022)
2026-08-21 12:01:52 +00:00

110 lines
6.3 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.

"""Две докстроки обещали то, чего в коде нет (#2464).
1. `QuarterDump` (nspd_client): «Default = только core, чтобы не сжигать rate-limit
на 17 запросов». Фактический дефолт `search_by_quarter` — `include_zouit=True`,
то есть 5 ЗОУИТ-слоёв входят в дефолтный вызов. Числа 17 тоже нет: grid-walk при
grid_n=7 даёт по 49 запросов на слой. Причём докстрока самого метода 640 строками
ниже пишет верно — «Default True»: правильный образец лежал рядом с дефектом.
2. `find_active_on_demand_job` (cadastre_fetch): «Если в БД есть FAILED on-demand за
последние 60 секунд — тоже None (чтобы повторно пробовать)». В SQL нет ни слова
'failed', ни какого-либо временного фильтра. Обещание вдвойне вредно: оно
подразумевало, что failed СТАРШЕ 60 секунд вернётся как активный (не вернётся),
и отправляло отлаживающего искать окно, которого нет.
Гейты сверяют утверждение докстроки с кодом, а не читаемость текста.
"""
from __future__ import annotations
import inspect
def _body(fn) -> str:
"""Тело функции без её докстроки.
НЕ `split('\"\"\"')[-1]`: SQL внутри сам обёрнут в тройные кавычки, поэтому
последний кусок — это хвост ПОСЛЕ запроса, и проверка шла бы по огрызку.
Отбрасываем ровно первую докстроку и склеиваем остальное обратно.
"""
части = inspect.getsource(fn).split('"""')
return '"""'.join(части[2:]) if len(части) > 2 else части[-1]
def test_quarter_dump_docstring_matches_the_real_default() -> None:
"""Головной 1: если докстрока обещает «только core» — дефолт обязан быть False.
На origin/main она это обещает, а `include_zouit` по умолчанию True.
"""
from app.services.scrapers.nspd_client import NSPDClient, QuarterDump
doc = inspect.getdoc(QuarterDump) or ""
default = inspect.signature(NSPDClient.search_by_quarter).parameters["include_zouit"].default
обещает_только_core = "Default = только core" in doc
assert not (обещает_только_core and default is True), (
f"докстрока QuarterDump обещает «Default = только core», "
f"а include_zouit по умолчанию {default}"
)
def test_quarter_dump_docstring_does_not_claim_17_requests() -> None:
"""Контроль числа: «17 запросов» противоречит grid-walk (49 запросов на слой).
Просто убрать слово «core» было бы недостаточно — довод про rate-limit
держался на выдуманном числе.
"""
from app.services.scrapers.nspd_client import QuarterDump
doc = inspect.getdoc(QuarterDump) or ""
assert "не сжигать rate-limit на 17 запросов" not in doc, (
"в докстроке осталось число 17, противоречащее grid-walk"
)
def test_on_demand_docstring_does_not_promise_a_60s_window() -> None:
"""Головной 2: обещание окна «60 секунд» должно подтверждаться SQL.
На origin/main докстрока его обещает, а в запросе нет ни 'failed',
ни временного фильтра.
"""
from app.services.site_finder.cadastre_fetch import find_active_on_demand_job
doc = inspect.getdoc(find_active_on_demand_job) or ""
тело = _body(find_active_on_demand_job)
обещает_окно = "за последние 60" in doc
есть_фильтр = any(kw in тело.lower() for kw in ("interval", "now()", "failed"))
assert not (обещает_окно and not есть_фильтр), (
f"докстрока обещает окно «за последние 60 секунд», а в SQL нет ни "
f"временного фильтра, ни статуса failed:\n{тело.strip()[:400]}"
)
def test_on_demand_sql_really_ignores_failed() -> None:
"""Характеризующий: запрос отбирает ровно три статуса, failed среди них нет.
Зелёный с обеих сторон — фиксирует фактическое поведение, о котором теперь
говорит докстрока. Если кто-то добавит окно, тест покраснеет и заставит
обновить и текст.
"""
from app.services.site_finder.cadastre_fetch import find_active_on_demand_job
тело = _body(find_active_on_demand_job)
assert "'queued', 'running', 'paused'" in тело, тело[:300]
assert "failed" not in тело.lower(), "в запросе появился failed — обнови докстроку"
def test_docstrings_state_the_actual_behaviour() -> None:
"""Контроль от вычёркивания: обе докстроки обязаны НАЗЫВАТЬ фактическое поведение.
Молча убрать неверную фразу — не починка: молчание читается как «всё хорошо».
"""
from app.services.scrapers.nspd_client import QuarterDump
from app.services.site_finder.cadastre_fetch import find_active_on_demand_job
qd = inspect.getdoc(QuarterDump) or ""
assert "include_zouit" in qd, "не назван фактический дефолт дампа"
od = inspect.getdoc(find_active_on_demand_job) or ""
assert "НИКОГДА" in od or "никогда" in od, (
"не сказано, что failed не возвращается независимо от давности"
)