[P2][tradein][backend][tests] Quality-gate тесты на P0-баги аудита (anchor n=2, dedup reprice, expected_sold anchor-only, block-page, median=0) #781

Closed
opened 2026-05-30 16:23:29 +00:00 by bot-analyst · 3 comments
Collaborator

Worker: исполняемый спек. Добавить регресс-тесты, фиксирующие P0-баги из аудита — чтобы фиксы #755/#753/#773/#754/#740 не откатились. Берись ПОСЛЕ мержа соответствующих fix-PR (иначе тесты будут падать на ещё-не-исправленном коде). Конфликт → коммент.

Задача

Закрыть quality-gate (#666): добавить unit/regression-тесты на 5 P0-дефектов, найденных на живом пилоте (322 оценки). Каждый тест — anti-regression guard для соответствующего fix-issue.

Тесты (каждый ссылается на свой fix-issue)

  1. anchor confidence n=2 (#755): при same-building anchor с n_comps < порога — confidence НЕ «high», headline не раздут uplift'ом. tradein-mvp/backend/tests/ (рядом с test_same_building_anchor.py).
  2. dedup_hash reprice/source_id (#753): один и тот же Avito item с разной ценой и разным ?context= → одинаковый compute_dedup_hash (стабильный source_id). test_rosreestr_dedup_key.py-стиль.
  3. expected_sold anchor-only (#773): anchor-путь без radius-comps (listings_clean пуст, median>0, ratio есть) → expected_sold_price > 0.
  4. block-page HTTP-200 (#754): _parse_html пустой на page=1 при 200 → raise (не тихий «end of pagination»); page>1 → graceful.
  5. median=0 insufficient_data (#740/#697): оценка без аналогов → insufficient_data=true, median=0; (frontend empty-state — отдельно).

⚠️ Обязательно — обновить устаревший тест

  • test_filter_outliers_passthrough_below_5_lots (найти: grep -rn 'passthrough_below_5\|filter_outliers' tradein-mvp/backend/tests/) — этот тест закрепляет баг «n<5 bypass Tukey» (часть anchor-проблемы #755). После фикса #755 он станет неверным ассертом → обновить под новое поведение (anchor-comps фильтруются/clip'ятся), НЕ оставлять зелёным на старом контракте.

Files

  • tradein-mvp/backend/tests/ — существующие: test_same_building_anchor.py, test_estimator_expected_sold.py, test_rosreestr_dedup_key.py, test_avito_*, test_filter_outliers* (точные имена — ls tradein-mvp/backend/tests/).

Definition of Done (бинарно)

  • 5 тестов добавлены (по одному на дефект выше), каждый ссылается на fix-issue в докстринге.
  • test_filter_outliers_passthrough_below_5_lots обновлён под пост-#755 контракт (или удалён с обоснованием).
  • cd tradein-mvp/backend && uv run pytest -k "anchor or dedup or expected_sold or avito or insufficient" → pass (на смерженных фиксах).
  • cd tradein-mvp/backend && uv run ruff check tests/ → clean.

Не делать (out of scope)

  • НЕ менять сам прод-код (тесты только; фиксы — в своих issue #755/#753/#773/#754/#740).
  • НЕ писать тест на ещё-не-смерженный фикс (дождаться merge fix-PR, иначе RED).

Зависимости

  • Depends on merge: #753 (dedup), #754 (block-page), #773 (expected_sold), #740 (insufficient_data). #755 (anchor) — needs-human, тест №1 + обновление filter_outliers ждут его решения.

Связано

  • Источник: canonical audit inbox/2026-05-30-1600-tradein-audit-decompose (finding #32). Quality-gate #666. Milestone Praktika demo 2026-06-01.
> Worker: исполняемый спек. Добавить регресс-тесты, фиксирующие P0-баги из аудита — чтобы фиксы #755/#753/#773/#754/#740 не откатились. Берись ПОСЛЕ мержа соответствующих fix-PR (иначе тесты будут падать на ещё-не-исправленном коде). Конфликт → коммент. ## Задача Закрыть quality-gate (#666): добавить unit/regression-тесты на 5 P0-дефектов, найденных на живом пилоте (322 оценки). Каждый тест — anti-regression guard для соответствующего fix-issue. ## Тесты (каждый ссылается на свой fix-issue) 1. **anchor confidence n=2** (#755): при same-building anchor с n_comps < порога — confidence НЕ «high», headline не раздут uplift'ом. `tradein-mvp/backend/tests/` (рядом с `test_same_building_anchor.py`). 2. **dedup_hash reprice/source_id** (#753): один и тот же Avito item с разной ценой и разным `?context=` → одинаковый `compute_dedup_hash` (стабильный source_id). `test_rosreestr_dedup_key.py`-стиль. 3. **expected_sold anchor-only** (#773): anchor-путь без radius-comps (listings_clean пуст, median>0, ratio есть) → `expected_sold_price > 0`. 4. **block-page HTTP-200** (#754): `_parse_html` пустой на page=1 при 200 → raise (не тихий «end of pagination»); page>1 → graceful. 5. **median=0 insufficient_data** (#740/#697): оценка без аналогов → `insufficient_data=true`, median=0; (frontend empty-state — отдельно). ## ⚠️ Обязательно — обновить устаревший тест - `test_filter_outliers_passthrough_below_5_lots` (найти: `grep -rn 'passthrough_below_5\|filter_outliers' tradein-mvp/backend/tests/`) — этот тест **закрепляет** баг «n<5 bypass Tukey» (часть anchor-проблемы #755). После фикса #755 он станет неверным ассертом → обновить под новое поведение (anchor-comps фильтруются/clip'ятся), НЕ оставлять зелёным на старом контракте. ## Files - `tradein-mvp/backend/tests/` — существующие: `test_same_building_anchor.py`, `test_estimator_expected_sold.py`, `test_rosreestr_dedup_key.py`, `test_avito_*`, `test_filter_outliers*` (точные имена — `ls tradein-mvp/backend/tests/`). ## Definition of Done (бинарно) - [ ] 5 тестов добавлены (по одному на дефект выше), каждый ссылается на fix-issue в докстринге. - [ ] `test_filter_outliers_passthrough_below_5_lots` обновлён под пост-#755 контракт (или удалён с обоснованием). - [ ] `cd tradein-mvp/backend && uv run pytest -k "anchor or dedup or expected_sold or avito or insufficient"` → pass (на смерженных фиксах). - [ ] `cd tradein-mvp/backend && uv run ruff check tests/` → clean. ## Не делать (out of scope) - НЕ менять сам прод-код (тесты только; фиксы — в своих issue #755/#753/#773/#754/#740). - НЕ писать тест на ещё-не-смерженный фикс (дождаться merge fix-PR, иначе RED). ## Зависимости - Depends on merge: #753 (dedup), #754 (block-page), #773 (expected_sold), #740 (insufficient_data). #755 (anchor) — needs-human, тест №1 + обновление filter_outliers ждут его решения. ## Связано - Источник: canonical audit `inbox/2026-05-30-1600-tradein-audit-decompose` (finding #32). Quality-gate #666. Milestone Praktika demo 2026-06-01.
bot-analyst added the
priority/p2
scope/backend
status/ready
tradein
labels 2026-05-30 16:23:36 +00:00
bot-analyst added this to the Praktika demo — Mon 2026-06-01 milestone 2026-05-30 16:23:37 +00:00
bot-backend self-assigned this 2026-05-30 16:54:14 +00:00
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-30 16:54:16 +00:00
bot-backend added
status/blocked
and removed
status/wip
labels 2026-05-30 16:56:09 +00:00
Collaborator

Проверено: тесты 2–5 уже существуют (добавлены fix-PR'ами), дублировать не нужно — gate #666 для них закрыт:

  • #2 dedup (#753)test_dedup_hash_stable_across_price_and_context_query + test_dedup_hash_strips_query_when_no_source_id (test_base_save_listings.py).
  • #3 expected_sold anchor-only (#773)test_expected_sold_fires_on_anchor_only_no_radius_comps (test_estimator_expected_sold.py).
  • #4 block-page HTTP-200 (#754)test_fetch_around_raises_content_blocked_on_page1_empty_html + test_fetch_around_page_gt1_empty_returns_gracefully (tests/scrapers/test_avito_anti_bot.py).
  • #5 median=0 insufficient (#740/#697)test_insufficient_when_median_zero + 3 родственных (test_insufficient_data_flag.py).

pytest -k "dedup or expected_sold or avito or insufficient" → 142 passed.

Остаток блокирован #755 (needs-human): тест #1 (anchor confidence n=2) + обновление test_filter_outliers_passthrough_below_5_lots зависят от решения по параметрам anchor (#755 ещё не смержен). → status/blocked до резолюции #755; тогда доделать эти два. Прод-код не трогался (issue tests-only).

Проверено: тесты 2–5 **уже существуют** (добавлены fix-PR'ами), дублировать не нужно — gate #666 для них закрыт: - **#2 dedup (#753)** → `test_dedup_hash_stable_across_price_and_context_query` + `test_dedup_hash_strips_query_when_no_source_id` (`test_base_save_listings.py`). - **#3 expected_sold anchor-only (#773)** → `test_expected_sold_fires_on_anchor_only_no_radius_comps` (`test_estimator_expected_sold.py`). - **#4 block-page HTTP-200 (#754)** → `test_fetch_around_raises_content_blocked_on_page1_empty_html` + `test_fetch_around_page_gt1_empty_returns_gracefully` (`tests/scrapers/test_avito_anti_bot.py`). - **#5 median=0 insufficient (#740/#697)** → `test_insufficient_when_median_zero` + 3 родственных (`test_insufficient_data_flag.py`). `pytest -k "dedup or expected_sold or avito or insufficient"` → 142 passed. **Остаток блокирован #755 (needs-human):** тест #1 (anchor confidence n=2) + обновление `test_filter_outliers_passthrough_below_5_lots` зависят от решения по параметрам anchor (#755 ещё не смержен). → `status/blocked` до резолюции #755; тогда доделать эти два. Прод-код не трогался (issue tests-only).
lekss361 modified the milestone from Praktika demo — Mon 2026-06-01 to Night batch — 2026-05-31 2026-05-30 19:39:07 +00:00
lekss361 added
status/ready
and removed
status/blocked
labels 2026-06-06 18:48:55 +00:00
Owner

Status actualize (06.06): все 5 fix-зависимостей влиты в main#755 (d1034bb), #753 (79a7900), #773 (ec84637), #754 (489666c), #740 (798fb12). Блокер снят → status/blockedstatus/ready (можно писать anti-regression тесты).

Status actualize (06.06): все 5 fix-зависимостей влиты в `main` — #755 (`d1034bb`), #753 (`79a7900`), #773 (`ec84637`), #754 (`489666c`), #740 (`798fb12`). Блокер снят → `status/blocked` → `status/ready` (можно писать anti-regression тесты).
lekss361 added
status/review
and removed
status/ready
labels 2026-06-06 19:17:36 +00:00
Owner

Тесты готовы → PR #1098. 13 anti-regression тестов (test_781_quality_gate.py) на #755/#753/#773/#754/#740, 325 passed, ruff clean. NB: test_filter_outliers_passthrough_below_5_lots НЕ переписан — проверка показала, что #755 не менял radius-path _filter_outliers (MAD-clip только в anchor), assert корректен. readyreview.

Тесты готовы → PR #1098. 13 anti-regression тестов (`test_781_quality_gate.py`) на #755/#753/#773/#754/#740, 325 passed, ruff clean. NB: `test_filter_outliers_passthrough_below_5_lots` НЕ переписан — проверка показала, что #755 не менял radius-path `_filter_outliers` (MAD-clip только в anchor), assert корректен. `ready` → `review`.
Sign in to join this conversation.
No project
No assignees
3 participants
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#781
No description provided.