# Объявленные пропуски сьюта tradein-mvp/backend. # # Пропуск, которого здесь нет, роняет прогон (хук в tests/conftest.py). Смысл: не # запретить пропуски, а запретить НЕЗАМЕТНЫЕ. Проверка, которая тихо перестала # исполняться, со временем расходится с кодом, и узнают об этом ровно тогда, # когда на неё понадобилось опереться (#2722, #2729, #2740). # # Формат: один nodeid в строке, без «[параметров]»; `#` — комментарий. # Прежде чем добавить строку, ответь: почему эту проверку нельзя выполнить ЗДЕСЬ # и где она выполняется вместо этого. Нет ответа — это не пропуск, а дыра. # # Список — НАДмножество сред: в CI Postgres есть (ci-tradein.yml поднимает # сервис-контейнер и собирает схему из backend/data/sql/), на ноутбуке без БД — # нет. Запись, чей пропуск не случился, безвредна; пропуск без записи — нет. # ── Реальный рендер PDF: нужны native-либы WeasyPrint (Pango/cairo/GObject) ──── # Где выполняется: внутри prod-образа — runner-stage tradein-mvp/backend/Dockerfile # ставит libcairo2 + libpango-1.0-0 + libpangoft2-1.0-0: # docker exec tradein-backend python -m pytest -q -m pdf_render tests/test_pdf_real_render.py # На голом ubuntu-latest в ci-tradein.yml этих либ нет (apt-шага в job'е нет). tests/test_pdf_real_render.py # ── Тесты против живой Postgres ─────────────────────────────────────────────── # В CI они ИДУТ (postgres-сервис в ci-tradein.yml, #2745) — записи ниже нужны # только для прогона на машине без БД. Именно эта группа разъехалась со схемой, # пока не бежала нигде: #2740 (houses.url стал NOT NULL) и #2744 # (test_gar_flats_loader падал до первого утверждения). Поднять локально: # docker run -d -p 5432:5432 -e POSTGRES_DB=tradein -e POSTGRES_USER=tradein \ # -e POSTGRES_PASSWORD=tradein postgis/postgis:16-3.4 # psql ... -f backend/data/sql/*.sql # порядок как в deploy-tradein.yml tests/tasks/test_backfill_house_coords_from_listings.py::test_real_transfers_agreeing_coords_skips_scattered_and_is_idempotent tests/tasks/test_cadastral_geo_match.py::test_real_knn_nearest_within_threshold_picked tests/test_audit_api.py::test_real_accounts_and_analytics_aggregate_inserted_rows tests/test_gar_flats_loader.py::test_upsert_and_canon_match_populates_gar_flat_count tests/test_house_dedup_merge.py::test_real_canon_clusterkey_and_geo_guard_merge_semantics tests/test_house_dedup_merge.py::test_real_fias_pass_cross_guard_and_identity_carryover tests/test_house_dedup_merge.py::test_real_fias_pass_ignores_geo_guard tests/test_house_dedup_merge.py::test_real_merge_is_reversible_via_journal tests/test_house_dedup_merge.py::test_real_merge_repoints_dedups_deletes_and_is_idempotent tests/test_user_events.py::test_real_record_event_inserts_row tests/test_3469_showcase_schedule.py::test_live_migration_puts_showcase_into_schedules_and_digest # Приватность/ретеншн (#2547) — тот же `_live_session()`. Приехали в main # параллельно с самим списком, поэтому первым же прогоном deploy-лэйна хук их и # поймал: 4 проверки не исполнились и не были объявлены. Проверено против живой # БД (схема из backend/data/sql/ по 233 включительно) — 29 passed, тесты живы. tests/test_data_erasure.py::test_real_erase_by_phone_does_not_match_different_number tests/test_data_erasure.py::test_real_erase_by_phone_finds_differently_formatted_number tests/test_data_erasure.py::test_real_erase_by_phone_finds_ru_trunk_prefix_variant tests/test_purge_expired_trade_in_data.py::test_real_purge_deletes_only_anonymous_expired_estimates # Payments retention (PR #2754), deep-review MEDIUM finding 2026-08-06 — тот же # `_live_session()`. Проверяют предполётную проверку purge против реального # retain_until/payments состояния (здоровая оплаченная строка не поднимает # тревогу и не блокирует джобу), не только SQL-текст. tests/test_purge_expired_trade_in_data.py::test_real_preflight_ignores_healthy_paid_row_flags_only_anomaly tests/test_purge_expired_trade_in_data.py::test_real_purge_not_wedged_by_healthy_paid_row # Диагноз оборванного прогона (#2764) — тот же `_live_session()`. Проверяет, что # дефолт mark_banned ('unknown') проходит CHECK-констрейнт из миграции 234: # на мок-лэйне (deploy-tradein.yml, DSN-заглушка) констрейнта нет вовсе. tests/test_2764_ban_kind_no_default.py::test_real_default_ban_kind_survives_the_check_constraint # Гейт номеров миграций (#2683) сверяется с origin/main и точкой ветвления. Где # git-эталона нет — прогон внутри prod-образа, экспорт исходников без .git — # проверять не с чем, и тест это ГОВОРИТ вслух вместо тихого зелёного. # В CI пропуска не бывает: при CI/GITHUB_ACTIONS та же ветка делает pytest.fail # (отсутствие эталона в пайплайне — сломанный гейт, а не «нечего проверять»), # а ci-tradein.yml/deploy-tradein.yml берут checkout с fetch-depth: 0 — при нём # checkout сам приносит refs/remotes/origin/*, отдельный git fetch не нужен и # из job-контейнера всё равно не проходит (run 6977, connection refused). tests/test_migration_numbering.py::test_applied_migration_is_not_renamed_or_deleted tests/test_migration_numbering.py::test_new_migration_takes_a_free_number # Повтор застрявших transient_error (#2674, PR #2843) — тот же `_live_session()`. # Проверяют ВЫБОРКУ очереди на живой схеме (кто попал в пакет прогона), а не текст # SQL: на мок-лэйне deploy-tradein.yml БД нет вовсе. В ci-tradein.yml они бегут # по-настоящему (Postgres + схема из data/sql) — там прогон и был красным на # origin/main и зелёным на ветке. Статическая половина файла # (test_retry_queue_is_not_bound_to_only_status) БД не требует и идёт в обоих лэйнах. tests/test_house_imv_retry_stuck.py::test_explicit_only_status_still_takes_exhausted_houses tests/test_house_imv_retry_stuck.py::test_stuck_transient_house_returns_to_the_queue_by_itself tests/test_house_imv_retry_stuck.py::test_transient_attempts_counter_only_counts_transient # MAJOR-1 fix, coverage probe (#2894, независимый ревью) — тот же `live_session` fixture # (self-skip через `_live_db_available()`, живёт только при реальном Postgres DSN). # Проверяет, что novostroyki-строка / geo_precision='city'-строка / price_rub=0-строка # физически не попадают в когорту (не только SQL-текст, который проверяется отдельным # статическим тестом test_cohort_sql_excludes_* в этом же файле, идущим на обоих лэйнах). tests/test_coverage_probe_endpoint.py::test_major1_cohort_excludes_novostroyki_and_city_precision_live # MAJOR-2 поведенческий пин (повторная проверка #2894) — та же `live_session` fixture. # Ловит мутацию «убрать FILTER у percentile_cont, оставив у count(*)», которую # текстовый тест test_max_age_outlier_days_passed_to_sql пропускал (подстрока # `days_on_market <= :max_age_days` встречается в SQL дважды). На мок-лэйне # (deploy-tradein.yml, DSN-заглушка) реальной БД нет — self-skip. tests/test_coverage_probe_endpoint.py::test_max_age_outlier_excluded_from_median_live # #2992 — гейт неизменной строки в апсертах listings / listing_sources. Шесть live-тестов # идут через реальный save_listings / upsert_listing_source на живом Postgres и меряют, # переписана ли строка, по ctid (save_listings коммитит — транзакционные счётчики # бесполезны). Без БД — skip; в CI Trade-In идут на postgres-сервисе (#2745). Свои # строки t2992-* тесты удаляют явно в finally. tests/test_2992_upsert_unchanged_gate.py::test_unchanged_rescrape_same_day_does_not_update_the_row tests/test_2992_upsert_unchanged_gate.py::test_changed_price_still_updates tests/test_2992_upsert_unchanged_gate.py::test_coalesce_backfill_still_updates tests/test_2992_upsert_unchanged_gate.py::test_next_day_rescrape_updates_even_if_unchanged tests/test_2992_upsert_unchanged_gate.py::test_skipped_row_still_yields_listing_id_for_downstream tests/test_2992_upsert_unchanged_gate.py::test_listing_sources_unchanged_rescrape_same_day_does_not_update # #3036 — house-поля с детальной страницы Авито → houses (fill-only). Live-тест ходит в # настоящую БД (в CI она есть, #2745), локально без TEST_DATABASE_URL пропускается. Строки # t3036-* тест удаляет в finally. tests/test_3036_detail_house_params_to_houses.py::test_live_fill_only_then_keep_then_unlinked_untouched # PR-A LATERAL-поиск предшественника в поле переобхода (#2659 продолжение) — тот же # `_live_session()`. Три live-теста вставляют синтетическую историю снимков (в т.ч. # с дырами) в ОДНОЙ транзакции и проверяют результат JOIN LATERAL/equality-join # прямым SELECT'ом в той же транзакции — cleanup через rollback (без commit), явный # DELETE не нужен. Без БД — skip; в CI Trade-In идут на postgres-сервисе (#2745). tests/test_revisit_floor_lateral_lookup.py::test_lateral_ignores_gaps_and_matches_dense_daily_history tests/test_revisit_floor_lateral_lookup.py::test_equality_join_loses_gapped_pairs_and_gives_a_smaller_floor tests/test_revisit_floor_lateral_lookup.py::test_missing_history_before_anchor_still_yields_no_floor_via_lateral # Эрозия признаков продавца (#3063, PR #3067) — тот же `_live_session()`. # Проверяют ПОВЕДЕНИЕ апсерта на живой схеме: что бедный re-scrape не обнуляет # is_homeowner/is_pro_seller/phones/sale_type (COALESCE держит), и обратное — что # настоящая смена признака всё ещё перезаписывает (COALESCE не сделал поля # write-once). SQL-текст проверяется отдельно статической половиной того же файла # (test_field_is_coalesce_protected_in_set + test_unchanged_gate_mirrors_the_set_clause), # она идёт на ОБОИХ лэйнах. В ci-tradein.yml эти два бегут по-настоящему # (postgres-сервис) — там прогон и был зелёным; в deploy-tradein.yml БД нет вовсе. tests/test_3063_seller_fields_not_eroded.py::test_poor_rescrape_does_not_erase_seller_fields tests/test_3063_seller_fields_not_eroded.py::test_real_change_still_overwrites # Потолки БД на движке (#3463) — поведенческая половина: проверяют, что запрос # длиннее потолка ОБРЫВАЕТСЯ (pg_sleep), что ожидание блокировки отваливается по # lock_timeout, и что `SET LOCAL` задачи планировщика перекрывает сессионный # потолок и не течёт за свою транзакцию. Всё это нельзя проверить без сервера: # потолок применяет Postgres, а не питон. Статическая половина того же файла # (test_engine_opens_connections_with_both_ceilings + # test_ceilings_are_coherent_with_declared_estimate_budgets) идёт на ОБОИХ лэйнах # и краснеет от снятия `connect_args` — проверено вручную 12.09. В ci-tradein.yml # эти пять бегут по-настоящему (postgres-сервис, #2745). tests/test_3463_db_timeouts.py::test_live_session_reports_both_ceilings tests/test_3463_db_timeouts.py::test_statement_over_ceiling_is_cancelled_not_hung tests/test_3463_db_timeouts.py::test_lock_wait_over_ceiling_is_aborted tests/test_3463_db_timeouts.py::test_set_local_statement_timeout_overrides_session_ceiling tests/test_3463_db_timeouts.py::test_set_local_is_scoped_to_its_transaction