All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 2m0s
Deploy / build-worker (push) Successful in 3m9s
Deploy / deploy (push) Successful in 1m25s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 9s
94 lines
4.7 KiB
Python
94 lines
4.7 KiB
Python
"""Числа в документации сверяются с кодом, а не живут отдельно (#2464).
|
||
|
||
Оба расхождения ниже — реальные, найденные 20.08.2026, и оба были незаметны: цифра в
|
||
комментарии не проверяется ничем, а расходится тихо при первой же правке констант.
|
||
|
||
• macro_coefficient: комментарий обещал сумму backed-весов 0.45. С #946 inflation
|
||
стал backed-каналом с весом 0.08, сумма стала 0.53 — комментарий не обновили.
|
||
|
||
• nspd_client.search_by_quarter: docstring обещал 6/11/22 запроса и ~3.6с/~6.6с/~13с.
|
||
Фактически три из пяти core-слоёв и ВСЕ zouit/risk идут grid-walk'ом по 49 запросов:
|
||
150/395/934 запроса, ~90с/~237с/~560с. Занижение в 25-42 раза — а объём запросов
|
||
здесь прямой фактор WAF-риска.
|
||
|
||
Гейт сверяет то, что НАПИСАНО, с тем, что ВЫЧИСЛЯЕТСЯ из констант. Красное здесь
|
||
означает «текст разошёлся с кодом», а не «текст непривычно отформатирован».
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
|
||
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")
|
||
|
||
import re
|
||
from pathlib import Path
|
||
|
||
|
||
def test_backed_weight_sum_in_comment_matches_constants() -> None:
|
||
"""Сумма из комментария обязана совпасть с суммой backed-констант."""
|
||
from app.services.forecasting import macro_coefficient as mc
|
||
|
||
src = Path(mc.__file__).read_text()
|
||
m = re.search(r"СУММА backed-весов = ([0-9.]+)", src)
|
||
assert m is not None, "в файле пропала строка «СУММА backed-весов = …» — гейт ослеп"
|
||
documented = float(m.group(1))
|
||
|
||
actual = round(
|
||
mc._W_RATE + mc._W_MORTG_RATE + mc._W_ISSUANCE + mc._W_OVERDUE + mc._W_INFLATION, 4
|
||
)
|
||
assert documented == actual, (
|
||
f"в комментарии сумма backed-весов {documented}, по константам {actual} — "
|
||
"текст разошёлся с кодом"
|
||
)
|
||
|
||
|
||
def _documented_request_counts(src: str) -> tuple[int, int, int]:
|
||
core = re.search(r"core only:.*?= (\d+) запрос", src)
|
||
zouit = re.search(r"\+zouit:\s*\+\d+\*\d+\s*= (\d+) запрос", src)
|
||
risks = re.search(r"\+risks:\s*\+\d+\*\d+\s*= (\d+) запрос", src)
|
||
assert core and zouit and risks, "в docstring пропала смета HTTP-запросов — гейт ослеп"
|
||
return int(core.group(1)), int(zouit.group(1)), int(risks.group(1))
|
||
|
||
|
||
def test_request_cost_in_docstring_matches_layer_dispatch() -> None:
|
||
"""Смета запросов обязана следовать из _GRID_WALK_LAYERS, а не из памяти автора."""
|
||
from app.services.scrapers import nspd_client as nc
|
||
|
||
src = Path(nc.__file__).read_text()
|
||
doc_core, doc_zouit, doc_risks = _documented_request_counts(src)
|
||
|
||
grid = set(nc._GRID_WALK_LAYERS)
|
||
core_layers = [
|
||
"parcels",
|
||
"buildings",
|
||
"territorial_zones",
|
||
"red_lines",
|
||
"engineering_structures",
|
||
]
|
||
grid_n = 7
|
||
per_grid = grid_n * grid_n
|
||
|
||
core_grid = sum(1 for c in core_layers if c in grid)
|
||
core_legacy = len(core_layers) - core_grid
|
||
n_zouit = len(nc.NSPDClient.QUARTER_ZOUIT_LAYERS)
|
||
n_risks = len(nc.NSPDClient.QUARTER_RISK_LAYERS)
|
||
|
||
exp_core = 1 + core_legacy + core_grid * per_grid
|
||
exp_zouit = exp_core + n_zouit * per_grid
|
||
exp_risks = exp_zouit + n_risks * per_grid
|
||
|
||
assert (doc_core, doc_zouit, doc_risks) == (exp_core, exp_zouit, exp_risks), (
|
||
f"docstring обещает {doc_core}/{doc_zouit}/{doc_risks} запросов, "
|
||
f"по диспетчеризации слоёв выходит {exp_core}/{exp_zouit}/{exp_risks}"
|
||
)
|
||
|
||
|
||
def test_grid_walk_membership_is_not_empty() -> None:
|
||
"""Контроль на сам гейт: если _GRID_WALK_LAYERS опустеет, расчёт станет
|
||
тавтологически совпадать с любой мелкой цифрой в docstring."""
|
||
from app.services.scrapers import nspd_client as nc
|
||
|
||
grid = set(nc._GRID_WALK_LAYERS)
|
||
assert len(grid) >= 10, f"grid-walk слоёв всего {len(grid)} — смета считается не по тому"
|
||
assert "territorial_zones" in grid, "core-слой выпал из grid-walk — пересчитать смету"
|