test(scrapers/krt): вернуть в прогон проверку многоблочной страницы (#2778) #2781

Merged
bot-backend merged 1 commit from test/2777-krt-multisite-no-dump into main 2026-08-07 09:48:54 +00:00
Collaborator

Refs #2778 (issue остаётся открытой — в ней запрошен PDF-образец для оставшихся 6 тестов)

Диагноз: 2 из 8 — выразимое, 6 из 8 — невыразимое

Секция «Образцы, которых нет в git» в skip_allowlist.txt содержала 8 записей и лечилась, по замыслу, одинаково: «закоммитить образцы». Разбор показал, что это два разных случая.

Где искали образцы (обоих нет)

место результат
<repo>/.playwright-mcp/ каталога нет вовсе
/Users/anton до 6 уровней шесть каталогов .playwright-mcp, ни в одном нет ekb-docs/
прод-VPS, find / -xdev пусто (по имени файла и по каталогу ekb-docs)
прод-БД ekb_krt_sites = 15 строк · ekb_ppt_tep = 0 строк

Ложный след, который стоит назвать. ekb_krt_sites.raw_block на проде заполнен во всех 15 строках (30 КБ) и выглядит как готовая замена дампу. Это не так: raw_block=block_text[:4000] (ekb_krt_registry.py:338) — уже очищенный от тегов текст. Вход парсера из него не восстановить; проверено выгрузкой (0 совпадений <strong>/<h2>).

KRT ×2 — выразимо без дампа → починено

Три вопроса:

  1. Вызывающий? Есть — сам тест, но он не исполнялся ни разу нигде.
  2. Считает ли кто-то то же самое рядом? Нет: соседние классы разбирают по ОДНОМУ блоку, многоблочность не покрыта ничем.
  3. Выразимо ли задуманное? Да — и паттерн уже в этом же файле (_BABUSHKINA_BLOCK с комментарием «не требует локального дампа»).

TestMultiSiteCountFromDumpTestMultiSitePage: страница из трёх блоков в двух годовых секциях, собранная из фрагментов, уже лежащих в файле, обёрнутых в <div>.

Что проверяется теперь и не проверялось раньше:

  • нумерация площадок на реальной странице начинается заново каждый год — «2.» встречается дважды, и site_name всё равно обязан быть уникальным (номер сам по себе ключом не является);
  • границы блоков не текут: договор 1-2/21.7-14 и «Брусника» остаются у своей площадки;
  • вид КРТ читается поблочно (третий блок — «нежилой застройки»);
  • ветка _extract_krt_section через find_parent (контейнер <div>) — одиночные блоки её не касаются вовсе.

Осознанная потеря, названная вслух (в комментарии у теста и в #2778): утверждение «на живой странице ЕКБ ≥14 площадок» синтетической страницей не заменяется. На проде ekb_krt_sites = 15, то есть по факту разбирается всё — но автоматической проверки этого больше нет.

PPT ×6 — невыразимо → задокументировано

Эти 6 проверяют извлечение таблиц из НАСТОЯЩЕГО PDF через pdfplumber. Соседний класс TestParsePptTep уже мокает pdfplumber целиком — синтетика тут просто дублировала бы его. Нужен файл; запрошен у Anton в #2778, там же — что оживёт, куда класть и почему нет блокеров (официальный градостроительный документ: без персональных данных, вне авторского права по ст. 1259 п. 6 ГК РФ).

Попутная находка в #2778: у парсера ППТ нет и прод-питания. Единственный seed в ekb_ppt_tep_sync.py:42"# VERIFY URL: ...", таск его пропускает с WARNING, отсюда ekb_ppt_tep = 0 на проде. Тот же файл (или рабочий URL) закрывает обе дыры сразу — и тесты, и acceptance #1136.

Сторож пропусков

Две строки убраны из tests/skip_allowlist.txt — иначе сторож ждал бы пропуска, которого больше нет. Комментарий секции переписан: сколько записей было, что с ними стало, какой файл нужен и от кого.

Верификация — прогон, а не конфиг

tests/services/scrapers/  →  292 passed, 6 skipped, exit 0
test_ekb_krt_registry.py  →  31 passed, 0 skipped

Было: в test_ekb_krt_registry.py 2 пропуска. Стало: ноль, и 4 исполняемых теста вместо 2 неисполняемых. Все 6 оставшихся пропусков названы в логе (-rs) и учтены сторожем (exit 0).

Refs #2778 (issue остаётся открытой — в ней запрошен PDF-образец для оставшихся 6 тестов) ## Диагноз: 2 из 8 — выразимое, 6 из 8 — невыразимое Секция «Образцы, которых нет в git» в `skip_allowlist.txt` содержала 8 записей и лечилась, по замыслу, одинаково: «закоммитить образцы». Разбор показал, что это два разных случая. ### Где искали образцы (обоих нет) | место | результат | |---|---| | `<repo>/.playwright-mcp/` | каталога нет вовсе | | `/Users/anton` до 6 уровней | шесть каталогов `.playwright-mcp`, ни в одном нет `ekb-docs/` | | прод-VPS, `find / -xdev` | пусто (по имени файла и по каталогу `ekb-docs`) | | прод-БД | `ekb_krt_sites` = 15 строк · `ekb_ppt_tep` = **0** строк | **Ложный след, который стоит назвать.** `ekb_krt_sites.raw_block` на проде заполнен во всех 15 строках (30 КБ) и выглядит как готовая замена дампу. Это не так: `raw_block=block_text[:4000]` (`ekb_krt_registry.py:338`) — уже **очищенный от тегов** текст. Вход парсера из него не восстановить; проверено выгрузкой (0 совпадений `<strong>`/`<h2>`). ### KRT ×2 — выразимо без дампа → починено Три вопроса: 1. **Вызывающий?** Есть — сам тест, но он не исполнялся ни разу нигде. 2. **Считает ли кто-то то же самое рядом?** Нет: соседние классы разбирают по ОДНОМУ блоку, многоблочность не покрыта ничем. 3. **Выразимо ли задуманное?** Да — и паттерн уже в этом же файле (`_BABUSHKINA_BLOCK` с комментарием «не требует локального дампа»). `TestMultiSiteCountFromDump` → `TestMultiSitePage`: страница из трёх блоков в двух годовых секциях, собранная из фрагментов, уже лежащих в файле, обёрнутых в `<div>`. Что проверяется теперь и не проверялось раньше: - нумерация площадок на реальной странице **начинается заново каждый год** — «2.» встречается дважды, и `site_name` всё равно обязан быть уникальным (номер сам по себе ключом не является); - границы блоков не текут: договор `1-2/21.7-14` и «Брусника» остаются у своей площадки; - вид КРТ читается поблочно (третий блок — «нежилой застройки»); - ветка `_extract_krt_section` через `find_parent` (контейнер `<div>`) — одиночные блоки её не касаются вовсе. **Осознанная потеря, названная вслух** (в комментарии у теста и в #2778): утверждение «на живой странице ЕКБ ≥14 площадок» синтетической страницей не заменяется. На проде `ekb_krt_sites` = 15, то есть по факту разбирается всё — но автоматической проверки этого больше нет. ### PPT ×6 — невыразимо → задокументировано Эти 6 проверяют извлечение таблиц из НАСТОЯЩЕГО PDF через pdfplumber. Соседний класс `TestParsePptTep` уже мокает pdfplumber целиком — синтетика тут просто дублировала бы его. Нужен файл; запрошен у Anton в **#2778**, там же — что оживёт, куда класть и почему нет блокеров (официальный градостроительный документ: без персональных данных, вне авторского права по ст. 1259 п. 6 ГК РФ). **Попутная находка в #2778:** у парсера ППТ нет и прод-питания. Единственный seed в `ekb_ppt_tep_sync.py:42` — `"# VERIFY URL: ..."`, таск его пропускает с WARNING, отсюда `ekb_ppt_tep = 0` на проде. Тот же файл (или рабочий URL) закрывает обе дыры сразу — и тесты, и acceptance #1136. ## Сторож пропусков Две строки убраны из `tests/skip_allowlist.txt` — иначе сторож ждал бы пропуска, которого больше нет. Комментарий секции переписан: сколько записей было, что с ними стало, какой файл нужен и от кого. ## Верификация — прогон, а не конфиг ``` tests/services/scrapers/ → 292 passed, 6 skipped, exit 0 test_ekb_krt_registry.py → 31 passed, 0 skipped ``` Было: в `test_ekb_krt_registry.py` 2 пропуска. Стало: ноль, и 4 исполняемых теста вместо 2 неисполняемых. Все 6 оставшихся пропусков названы в логе (`-rs`) и учтены сторожем (exit 0).
bot-backend added 1 commit 2026-08-07 08:58:05 +00:00
test(scrapers/krt): вернуть в прогон проверку многоблочной страницы (#2778)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 18s
CI / changes (pull_request) Successful in 20s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
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 3m45s
CI / backend-tests (pull_request) Successful in 16m44s
bc8d00ea43
`TestMultiSiteCountFromDump` читал `.playwright-mcp/ekb-docs/krt_page_raw.html`
и пропускался всегда: файла нет ни в репозитории, ни на дисках (шесть каталогов
`.playwright-mcp` — ни в одном нет `ekb-docs/`), ни на прод-VPS (`find / -xdev`
по имени и по каталогу — пусто).

Восстановить из БД тоже нельзя, хотя выглядит будто можно: на проде
`ekb_krt_sites` = 15 строк с непустым `raw_block`, но там лежит НЕ HTML —
`raw_block=block_text[:4000]` (ekb_krt_registry.py:338), то есть уже очищенный
от тегов текст. Вход парсера из него не собрать.

Зато свойство, ради которого тесты писались, от дампа не зависит: страница
собирается из блоков, которые УЖЕ лежат в этом тест-файле (`_BRUSNIKA_BLOCK` +
`_BABUSHKINA_BLOCK` + третий, «нежилой»), обёрнутых в один `<div>`. Проверяется:
  • три блока в двух годовых секциях → три площадки;
  • нумерация на реальной странице начинается заново каждый год, поэтому «2.»
    встречается дважды — и site_name обязан остаться уникальным;
  • границы блоков не текут: договор 1-2/21.7-14 и «Брусника» остаются у своей
    площадки, не прилипая к соседям;
  • вид КРТ читается поблочно (третий — «нежилой застройки»).

Плюс это первый тест, который проходит через ветку `_extract_krt_section` с
`find_parent` (контейнер `<div>`); одиночные блоки её не касаются вовсе.

ЧЕГО ЗАМЕНА НЕ ПРОВЕРЯЕТ — сказано вслух в комментарии у теста и в #2778:
утверждение «на живой странице ≥14 площадок» синтетикой не заменяется. Оно
вернётся, когда в репозитории появится образец страницы.

Сторож пропусков: две строки убраны из tests/skip_allowlist.txt — иначе он ждал
бы пропуска, которого больше нет. Оставшиеся 6 (PDF-образец ППТ) переписаны с
указанием, какой файл нужен, от кого и что оживёт: #2778.

Верификация: tests/services/scrapers/ — 292 passed, 6 skipped, exit 0. Все 6
пропусков названы в логе (`-rs`) и учтены сторожем. В самом
test_ekb_krt_registry.py пропусков больше нет: 31 passed.

Refs #2778
bot-backend closed this pull request 2026-08-07 09:30:32 +00:00
bot-backend reopened this pull request 2026-08-07 09:30:33 +00:00
Author
Collaborator

Первый прогон CI / backend-tests (run 6961) был красным не из-за этого PR. Диффа тут два файла — test_ekb_krt_registry.py и skip_allowlist.txt, — а упало tests/services/test_weather_cache.py:283.

Разобрал, потому что «наверное флейк, перезапусти» — плохой ответ. Оказалось не флейк: тест требует гарантии, которой в коде нет.

E  ожидался 1 сетевой вызов, было 2

Тест поднимает 16 потоков и утверждает «Single-flight под lock'ом — РОВНО один реальный вызов». weather_cache.py:283-287 в комментарии говорит обратное: сетевой вызов сделан вне lock'а сознательно (#1370), «cold-start на ОДИН ключ может породить несколько параллельных запросов… что приемлемо». Локально 5 прогонов подряд зелёные — при GIL и мгновенном моке первый поток обычно успевает сложить результат раньше остальных; на нагруженном раннере не успевает.

Заведено отдельно: #2783 (там же развилка — чинить тест под фактический контракт или делать настоящий per-key single-flight). Сюда не тащу: другой подсистемы и требует решения, а не правки.

Прогон перезапущен (rerun через API этой версии Forgejo не поддерживается — 404, поэтому close/reopen): runs 6974/6975.

Первый прогон `CI / backend-tests` (run 6961) был красным **не из-за этого PR**. Диффа тут два файла — `test_ekb_krt_registry.py` и `skip_allowlist.txt`, — а упало `tests/services/test_weather_cache.py:283`. Разобрал, потому что «наверное флейк, перезапусти» — плохой ответ. Оказалось не флейк: тест требует гарантии, которой в коде нет. ``` E ожидался 1 сетевой вызов, было 2 ``` Тест поднимает 16 потоков и утверждает «Single-flight под lock'ом — РОВНО один реальный вызов». `weather_cache.py:283-287` в комментарии говорит обратное: сетевой вызов сделан **вне** lock'а сознательно (#1370), «cold-start на ОДИН ключ может породить несколько параллельных запросов… что приемлемо». Локально 5 прогонов подряд зелёные — при GIL и мгновенном моке первый поток обычно успевает сложить результат раньше остальных; на нагруженном раннере не успевает. Заведено отдельно: #2783 (там же развилка — чинить тест под фактический контракт или делать настоящий per-key single-flight). Сюда не тащу: другой подсистемы и требует решения, а не правки. Прогон перезапущен (rerun через API этой версии Forgejo не поддерживается — 404, поэтому close/reopen): runs 6974/6975.
bot-backend merged commit 90c3e7e490 into main 2026-08-07 09:48:54 +00:00
bot-backend deleted branch test/2777-krt-multisite-no-dump 2026-08-07 09:48:54 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2781
No description provided.