test(tradein): quality-gate anti-regression тесты на 5 P0-фиксов (#781) #1098

Merged
bot-reviewer merged 1 commit from feat/781-quality-gate-tests into main 2026-06-06 19:27:24 +00:00
Owner

Closes #781. Tests-only — прод-код не менялся.

Что

Anti-regression guard'ы на 5 P0-дефектов аудита (фиксы уже в main: #755/#753/#773/#754/#740) — чтобы не откатились. 13 тестов в новом tests/test_781_quality_gate.py:

Fix Тесты
#755 anchor n=2 safe-guard anchor не фаерит при n<порога → headline остаётся на radius-median; pure-unit: confidence никогда не 'high'
#753 stable dedup_hash reprice (same source_id, разная цена) → тот же hash; разный ?context= → тот же hash; +sanity distinct
#773 expected_sold anchor-only radius=[], anchor fires, ratio есть → expected_sold>0; ratio=None → None
#754 avito block-page HTTP-200 page=1 0 cards → raise AvitoContentBlockedError; page>1 → graceful
#740 median=0 insufficient_data нет аналогов → insufficient_data=true, median=0; +serialization

⚠️ Отклонение от спека issue (verify-don't-trust)

Issue предполагал, что test_filter_outliers_passthrough_below_5_lots нужно переписать под пост-#755 контракт. Проверка показала иначе: #755 добавил MAD-clip ТОЛЬКО в _compute_same_building_anchor, а НЕ в radius-path _filter_outliers. n<5 bypass в radius-фильтре корректен и намеренен → assert не менялся, добавлен только пояснительный докстринг. (reviewer — обратите внимание на этот пункт.)

Verify

uv run pytest325 passed, 0 failures; ruff check clean.

Closes #781. Tests-only — прод-код не менялся. ## Что Anti-regression guard'ы на 5 P0-дефектов аудита (фиксы уже в main: #755/#753/#773/#754/#740) — чтобы не откатились. 13 тестов в новом `tests/test_781_quality_gate.py`: | Fix | Тесты | |---|---| | **#755** anchor n=2 safe-guard | anchor не фаерит при n<порога → headline остаётся на radius-median; pure-unit: confidence никогда не 'high' | | **#753** stable dedup_hash | reprice (same source_id, разная цена) → тот же hash; разный `?context=` → тот же hash; +sanity distinct | | **#773** expected_sold anchor-only | radius=[], anchor fires, ratio есть → `expected_sold>0`; ratio=None → None | | **#754** avito block-page HTTP-200 | page=1 0 cards → raise `AvitoContentBlockedError`; page>1 → graceful | | **#740** median=0 insufficient_data | нет аналогов → `insufficient_data=true`, median=0; +serialization | ## ⚠️ Отклонение от спека issue (verify-don't-trust) Issue предполагал, что `test_filter_outliers_passthrough_below_5_lots` нужно переписать под пост-#755 контракт. **Проверка показала иначе:** #755 добавил MAD-clip ТОЛЬКО в `_compute_same_building_anchor`, а НЕ в radius-path `_filter_outliers`. n<5 bypass в radius-фильтре корректен и намеренен → assert не менялся, добавлен только пояснительный докстринг. (reviewer — обратите внимание на этот пункт.) ## Verify `uv run pytest` → **325 passed, 0 failures**; `ruff check` clean.
lekss361 added 1 commit 2026-06-06 19:17:25 +00:00
test(tradein): quality-gate tests for 5 P0 audit fixes (Refs #781)
All checks were successful
CI / changes (push) Successful in 7s
CI / backend-tests (push) Has been skipped
CI / changes (pull_request) Successful in 5s
CI / backend-tests (pull_request) Has been skipped
159a02a800
Anti-regression guards for PRs #877/#761/#784/#779/#743 (issues #755/#753/#773/#754/#740).
All 5 defects had no dedicated lock test -- any refactor could silently re-introduce them.

New file test_781_quality_gate.py (13 tests):
  #755: anchor n=2 < min_comps=4 does not fire; pure-unit confidence cap (n<5 != high)
  #753: compute_dedup_hash stable across reprice + ?context= query strip; source_id priority
  #773: expected_sold_price_rub > 0 on anchor-only path (radius=[]) when ratio present
  #754: page=1 HTTP-200 block raises AvitoContentBlockedError; page>1 graceful return
  #740: AggregatedEstimate.insufficient_data=True when median=0; survives model_dump()

Updated test_estimator_pure_units.py:
  test_filter_outliers_passthrough_below_5_lots -- added docstring clarifying this tests
  the radius-path _filter_outliers (n<5 bypass Tukey is unchanged by #755); #755 added
  MAD-clip only to _compute_same_building_anchor, not to the radius-path filter.

325 tests pass under -k anchor|dedup|expected_sold|avito|insufficient|filter_outliers.
ruff clean.
bot-reviewer reviewed 2026-06-06 19:27:17 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

Tests-only (0 прод-кода), 13 anti-regression guard'ов на 5 P0-фиксов:

  • #755-scope claim VERIFIED CORRECT: radius _filter_outliers n<5 bypass НЕ тронут #755 (MAD-clip/min_comps=4/confidence-cap только в anchor _compute_same_building_anchor). Решение автора не переписывать is lots assert — верное, не ложное оправдание. verify-don't-trust.
  • Фикстуры присутствуют: avito_blockpage_sample.html + avito_serp_sample.html есть (git ls-tree) — module-level read_text не уронит collection.
  • Все символы реальны (estimate_quality, _compute_same_building_anchor, ScrapedLot.compute_dedup_hash, AvitoContentBlockedError, AggregatedEstimate.insufficient_data, AvitoScraper.fetch_around/_fetch_serp_html/sleep_between_requests).
  • Тесты non-vacuous: каждая группа имеет positive + control (reprice/context-strip/distinct, anchor-fire/no-ratio, median=0/>0). Реверт фикса ломает assert.
  • Всё мокается (MagicMock db, no network). deploy-tradein pytest-gate (325 passed) валидирует.

Merge → deploy-tradein verify.

<!-- gendesign-review-bot: sha=159a02a verdict=approve --> ✅ **APPROVE** Tests-only (0 прод-кода), 13 anti-regression guard'ов на 5 P0-фиксов: - **#755-scope claim VERIFIED CORRECT**: radius `_filter_outliers` n<5 bypass НЕ тронут #755 (MAD-clip/min_comps=4/confidence-cap только в anchor `_compute_same_building_anchor`). Решение автора не переписывать `is lots` assert — верное, не ложное оправдание. ✅ verify-don't-trust. - **Фикстуры присутствуют**: `avito_blockpage_sample.html` + `avito_serp_sample.html` есть (git ls-tree) — module-level read_text не уронит collection. - **Все символы реальны** (estimate_quality, _compute_same_building_anchor, ScrapedLot.compute_dedup_hash, AvitoContentBlockedError, AggregatedEstimate.insufficient_data, AvitoScraper.fetch_around/_fetch_serp_html/sleep_between_requests). - **Тесты non-vacuous**: каждая группа имеет positive + control (reprice/context-strip/distinct, anchor-fire/no-ratio, median=0/>0). Реверт фикса ломает assert. - Всё мокается (MagicMock db, no network). deploy-tradein pytest-gate (325 passed) валидирует. Merge → deploy-tradein verify.
bot-reviewer merged commit ea5c1e29f6 into main 2026-06-06 19:27:24 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 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#1098
No description provided.