# Объявленные пропуски сьюта backend/. # # Пропуск, которого здесь нет, роняет прогон (хук в tests/conftest.py). Смысл: не # запретить пропуски, а запретить НЕЗАМЕТНЫЕ. Проверка, которая тихо перестала # исполняться, со временем расходится с кодом, и узнают об этом ровно тогда, # когда на неё понадобилось опереться (#2722, #2729, #2740). # # Формат: один nodeid в строке, без «[параметров]»; `#` — комментарий. # Прежде чем добавить строку, ответь: почему эту проверку нельзя выполнить ЗДЕСЬ # и где она выполняется вместо этого. Нет ответа — это не пропуск, а дыра. # # Список — НАДмножество сред: на CI (ubuntu + libpango + postgres-сервис) часть # записей не срабатывает, на ноутбуке без них — срабатывает. Запись, чей пропуск # не случился, безвредна; пропуск без записи — нет. # ── WeasyPrint: нужны native-либы (Pango/cairo/GObject) ─────────────────────── # В CI ЭТИ ТЕСТЫ ИДУТ: ci.yml ставит libcairo2/libpango-1.0-0/libpangoft2-1.0-0. # Записи нужны только для macOS-dev, где libgobject-2.0-0 нет. tests/api/v1/test_parcels_forecast.py::test_export_forecast_pdf_returns_pdf tests/services/exporters/test_report_pdf.py::TestConfidenceSectionParity::test_dict_shaped_factor_produces_valid_pdf tests/services/exporters/test_report_pdf.py::TestFullReportExport::test_accepts_as_dict_input tests/services/exporters/test_report_pdf.py::TestFullReportExport::test_returns_non_trivial_length tests/services/exporters/test_report_pdf.py::TestFullReportExport::test_returns_pdf_magic_bytes tests/services/exporters/test_report_pdf.py::TestGracefulPartialReport::test_empty_report_still_valid_pdf tests/services/exporters/test_report_pdf.py::TestGracefulPartialReport::test_garbage_input_does_not_crash tests/services/exporters/test_report_pdf.py::TestGracefulPartialReport::test_partial_report_some_sections tests/services/generative/test_exporters.py::test_pdf_export_produces_pdf_bytes tests/test_layout_tz_pdf.py # ── phantom-column gate: нужна КОПИЯ ПРОДОВОЙ схемы ─────────────────────────── # Смысл этих тестов — поймать колонку, которой нет в реальной БД, поэтому пустой # сервис-контейнер их не заменяет: против пустой схемы они дали бы красноту, не # относящуюся к делу. Условие: TEST_DATABASE_URL на SSH-туннель к проду # (`ssh -N gendesign` → localhost:15432), см. tests/integration/conftest.py. # ЗАПУСКАТЬ ВРУЧНУЮ после правок SQL-запросов в app/services/**. tests/integration/test_analyze_parcels_sql.py::TestIrdOverlapSql::test_explain_ird_overlap tests/integration/test_analyze_parcels_sql.py::TestVelocityCompetitorsSql::test_explain_competitors tests/integration/test_analyze_parcels_sql.py::TestNeighborsSummarySql::test_explain_neighbors_summary tests/integration/test_phantom_columns.py::TestCadGeoTables::test_parcel_centroid_query tests/integration/test_phantom_columns.py::TestDomrfKnFlats::test_avg_price_query tests/integration/test_phantom_columns.py::TestDomrfKnFlats::test_supply_batch_query tests/integration/test_phantom_columns.py::TestDomrfKnObjects::test_competitors_full_cte_query tests/integration/test_phantom_columns.py::TestDomrfKnObjects::test_competitors_radius_query tests/integration/test_phantom_columns.py::TestDomrfKnObjects::test_velocity_competitor_query_columns tests/integration/test_phantom_columns.py::TestEkburgConstructionPermits::test_permits_rns_columns tests/integration/test_phantom_columns.py::TestEkburgConstructionPermits::test_permits_rve_columns tests/integration/test_phantom_columns.py::TestEkburgConstructionPermits::test_recent_permits_query tests/integration/test_phantom_columns.py::TestMvLayoutVelocity::test_velocity_by_room_bucket tests/integration/test_phantom_columns.py::TestObjectiveTables::test_objective_corpus_room_month_columns tests/integration/test_phantom_columns.py::TestObjectiveTables::test_objective_mapping_columns tests/integration/test_phantom_columns.py::TestObjectiveTables::test_sold_count_query # ── SQL-логика на живой Postgres ────────────────────────────────────────────── # В CI ЭТИ ТЕСТЫ ИДУТ с #2745 (postgres-сервис в ci.yml); до него не бежали ни # разу с момента написания. Схема не нужна — строят себе временные таблицы. # Локально: docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=... postgres:16 tests/sql/test_ddu_price_indicator.py::test_basis_and_previous_index tests/sql/test_ddu_price_indicator.py::test_packaged_deal_bucketed_by_per_unit_area tests/sql/test_ddu_price_indicator.py::test_prev_period_value_skips_filtered_quarter tests/sql/test_mv_layout_velocity_weighted_avg.py::TestWeightedAvgFormula::test_hand_computed_weighted_average tests/sql/test_mv_layout_velocity_weighted_avg.py::TestWeightedAvgFormula::test_no_zero_months_weighted_equals_naive tests/sql/test_mv_layout_velocity_weighted_avg.py::TestWeightedAvgFormula::test_nullif_prevents_division_by_zero tests/sql/test_mv_layout_velocity_weighted_avg.py::TestWeightedAvgFormula::test_weighted_differs_from_naive_sparse_project tests/sql/test_mv_layout_velocity_weighted_avg.py::TestWeightedAvgFormula::test_zero_deal_months_skew_naive_avg tests/sql/test_velocity_alerts.py::test_lookback_anchors_to_latest_data_month tests/sql/test_velocity_alerts.py::test_sharp_drop_is_flagged # ── Живая сеть NSPD (nspd.gov.ru) ───────────────────────────────────────────── # Ходят в внешний сервис: в гейте это флейк и зависимость от чужого аптайма. # Запуск вручную: uv run pytest tests/scrapers/ -m slow / -m integration -s tests/scrapers/test_nspd_bulk_client.py::test_list_objects_in_building_real tests/scrapers/test_nspd_bulk_client.py::test_search_by_quarter_empty tests/scrapers/test_nspd_bulk_client.py::test_search_by_quarter_real_ekb tests/scrapers/test_nspd_bulk_client.py::test_wms_feature_info_real tests/scrapers/test_nspd_grid_walk.py::test_live_nspd_grid_walk_skipped # ── Образец, которого нет в git ─────────────────────────────────────────────── # ДОЛГ, а не норма. Было 8 записей; 2 из них (test_ekb_krt_registry.py:: # TestMultiSiteCountFromDump) сняты в #2778: дампа `krt_page_raw.html` не # оказалось НИГДЕ — ни в репозитории, ни на дисках, ни на проде (в БД лежит # `raw_block` = уже очищенный текст, вход парсера из него не восстановить), — # зато свойство, которое они проверяли (несколько блоков на странице, уникальные # site_name), выразимо без дампа и теперь проверяется на многоблочной странице, # собранной из блоков, уже лежащих в том же тест-файле. # # Оставшиеся 6 так не лечатся: они проверяют извлечение таблиц из НАСТОЯЩЕГО PDF # через pdfplumber, соседний класс TestParsePptTep уже мокает pdfplumber целиком. # Нужен файл `ppt2018_22823_poyasnit_PPT.pdf` (или рабочий URL на ГИСОГД ЕКБ) — # запрошен у Anton в #2778, там же список того, что оживёт. Причин не коммитить # нет: официальный градостроительный документ, без персональных данных. # После получения — положить в tests/fixtures/, поправить `_REAL_PDF_PATH`, # убрать эти шесть строк. tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_phasing_has_area tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_phasing_has_rows tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_raw_tables_not_empty tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_tep_has_rows tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_zone_balance_has_itogo tests/services/scrapers/test_ekb_ppt_tep_parser.py::TestParsePptTepRealPdf::test_zone_balance_has_rows # ── #2956: свежесть data-table источника считается по успешным строкам ──────── # Нужен живой Postgres: тест создаёт ВРЕМЕННЫЕ копии всех таблиц реестра freshness # и гоняет по ним настоящий SQL compute_freshness. В CI ЭТИ ТЕСТЫ ИДУТ — postgres- # сервис поднят (#2745), как и для соседних tests/sql/*. Записи нужны только для # машины без БД и без туннеля на 15432. tests/sql/test_2956_freshness_ignores_failed_dumps.py::test_failed_dumps_do_not_refresh_the_clock tests/sql/test_2956_freshness_ignores_failed_dumps.py::test_successful_dump_still_counts_as_fresh tests/sql/test_2956_freshness_ignores_failed_dumps.py::test_attempt_is_still_recorded tests/sql/test_2956_freshness_ignores_failed_dumps.py::test_only_failures_means_no_success_at_all # ── #2464: контракт суффиксов в /admin/leads/stats ──────────────────────────── # Нужен живой Postgres: тест создаёт ВРЕМЕННЫЕ prinzip_leads/prinzip_deals и # вызывает leads_stats на данных, где итог заведомо не равен окну. В CI ЭТИ ТЕСТЫ # ИДУТ (postgres-сервис, #2745); записи нужны для машины без БД и без туннеля. tests/sql/test_2464_leads_stats_suffix_contract.py::test_window_suffixed_fields_match_the_window tests/sql/test_2464_leads_stats_suffix_contract.py::test_total_suffixed_fields_are_all_time tests/sql/test_2464_leads_stats_suffix_contract.py::test_revenue_and_deals_are_named_by_their_scope tests/sql/test_2464_leads_stats_suffix_contract.py::test_window_months_present_on_empty_data # ── #2464: дедуп land_reservation (миграция 189) ────────────────────────────── # Нужен живой Postgres: тесты создают ВРЕМЕННУЮ копию таблицы, проверяют семантику # UNIQUE NULLS NOT DISTINCT и репетируют миграцию на засеянных дублях. В CI ИДУТ # (postgres-сервис, #2745); записи нужны для машины без БД и без туннеля. tests/sql/test_2464_land_reservation_dedup.py::test_nulls_not_distinct_deduplicates tests/sql/test_2464_land_reservation_dedup.py::test_plain_unique_does_not_deduplicate tests/sql/test_2464_land_reservation_dedup.py::test_records_with_act_number_still_deduplicate tests/sql/test_2464_land_reservation_dedup.py::test_different_parcels_are_not_collapsed tests/sql/test_2464_land_reservation_dedup.py::test_migration_dedup_statement_matches_the_key tests/sql/test_2464_land_reservation_dedup.py::test_migration_body_runs_on_a_prod_shaped_replica # ── #2464: единственный дефолтный профиль весов (миграция 190) ──────────────── # Нужен живой Postgres: тесты создают ВРЕМЕННУЮ user_weight_profiles, применяют # миграцию и проверяют, что вторая установка дефолта отвергается базой. В CI ИДУТ # (postgres-сервис, #2745); записи нужны для машины без БД и без туннеля. tests/sql/test_2464_default_profile_unique.py::test_second_default_is_rejected_by_the_database tests/sql/test_2464_default_profile_unique.py::test_without_migration_two_defaults_slip_through tests/sql/test_2464_default_profile_unique.py::test_reassigning_default_still_works tests/sql/test_2464_default_profile_unique.py::test_different_users_keep_their_own_defaults # ── #2464: корзина площади «н/д» в supply-only (best_layouts) ───────────────── # Нужен живой Postgres: тесты создают ВРЕМЕННУЮ таблицу objective_lots, которая # затеняет боевую в пределах сессии, и прогоняют НАСТОЯЩИЙ _SUPPLY_ONLY_LOTS_SQL # на засеянных лотах. В CI ИДУТ (postgres-сервис, #2745); записи нужны для машины # без БД и без туннеля. tests/sql/test_2464_area_bin_unknown.py::test_lot_without_area_is_not_counted_as_tiny tests/sql/test_2464_area_bin_unknown.py::test_unknown_area_gets_its_own_bucket tests/sql/test_2464_area_bin_unknown.py::test_total_lots_preserved tests/sql/test_2464_area_bin_unknown.py::test_normal_buckets_unchanged # ── #2464: backfill act_date (миграция 191) ────────────────────────────────── # Нужен живой Postgres: тесты создают ВРЕМЕННУЮ копию land_reservation в прод-форме # (9+2 строки с датой Генплана + контрольные посторонние) и прогоняют ТЕЛО миграции # целиком. В CI ИДУТ (postgres-сервис, #2745); записи нужны для машины без БД. tests/sql/test_2464_act_date_backfill.py::test_genplan_dates_are_replaced_with_real_ones tests/sql/test_2464_act_date_backfill.py::test_no_2004_rows_left_in_target_documents tests/sql/test_2464_act_date_backfill.py::test_other_documents_with_same_date_are_untouched tests/sql/test_2464_act_date_backfill.py::test_correct_rows_do_not_move tests/sql/test_2464_act_date_backfill.py::test_migration_is_idempotent tests/sql/test_2464_act_date_backfill.py::test_without_the_migration_rows_stay_wrong # ── #2986: бизнес-ключ gisogd_permits по source_key (миграция 191) ──────────── # Нужен живой Postgres: тесты создают ВРЕМЕННУЮ копию таблицы в прод-форме (со СТАРЫМ # ключом), прогоняют тело миграции и проверяют, что разрешение и изменения к нему # живут раздельно, а межсхемный дубль по-прежнему склеивается. Два гейта на лоадер # (GROUP_CODE и цель ON CONFLICT) базы НЕ требуют и в этот список НЕ входят. # В CI ИДУТ (postgres-сервис, #2745); записи нужны для машины без БД. tests/sql/test_2986_permits_source_key.py::test_old_key_collapses_permit_and_its_amendment tests/sql/test_2986_permits_source_key.py::test_after_migration_both_documents_survive tests/sql/test_2986_permits_source_key.py::test_cross_schema_duplicate_still_merges tests/sql/test_2986_permits_source_key.py::test_migration_allows_the_izmeneniya_group # #2998 — горизонт партиций rosreestr_deals. Четыре DB-теста поднимают rosreestr_deals из # 01_schema в СХЕМЕ-ПЕСОЧНИЦЕ (герметично, прод не трогают), применяют миграцию 193 и # читают горизонт из pg_inherits: до 193 красно по значению (01-схема кончается на 2026q1), # после — партиция есть на публикуемый квартал + на следующий; 193 идемпотентна. # В CI ИДУТ (postgres-сервис, #2745); записи нужны для машины без БД. Календарный # test_calendar_helper_matches_known_publication базы НЕ требует и в список НЕ входит. tests/sql/test_2998_rosreestr_partition_horizon.py::test_schema_01_alone_is_red_for_the_publishable_quarter tests/sql/test_2998_rosreestr_partition_horizon.py::test_migration_193_is_idempotent_and_closes_the_gap tests/sql/test_2998_rosreestr_partition_horizon.py::test_partition_exists_for_every_publishable_quarter tests/sql/test_2998_rosreestr_partition_horizon.py::test_partition_exists_one_quarter_ahead