From cac81d03185d1c61ad4ded6b158e0b3dfc12203c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Wed, 7 Oct 2026 05:18:54 +0400 Subject: [PATCH] =?UTF-8?q?test(golden):=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= =?UTF-8?q?=20=D1=8F=D0=B4=D1=80=D0=B0=20=D0=BF=D0=BE=D0=B4=20=D0=BE=D0=B1?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BB=D1=91=D0=BD=D0=BD=D1=8B=D0=B5=20golden?= =?UTF-8?q?=20fixtures=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test_mapping_golden: число снимков проверяется снизу (MIN_SNAPSHOTS = 113: rb 42, schastl 30, osv-dkb 22, synthetic 19), новые снимки fixtures проходят те же инварианты и не ломают тест; известные коды вне плана счетов — явный список KNOWN_OUT_OF_PLAN (60.АВ и 10 субсчетов 76 пакета ДКБ), новый код по-прежнему валит тест. - test_consolidation_fixtures: UNMAPPED_TOTAL 1381 → 1379 — две строки свода РБ находят контрагента по ИНН из названия (tabular-parser #15). Маппинг ядра без изменений: 113 снимков, 129 документов, 24 384 строки за ~7 с, все инварианты выполняются. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2 --- api/tests/test_consolidation_fixtures.py | 4 ++- api/tests/test_mapping_golden.py | 38 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/api/tests/test_consolidation_fixtures.py b/api/tests/test_consolidation_fixtures.py index 0262b77..fd51cfc 100644 --- a/api/tests/test_consolidation_fixtures.py +++ b/api/tests/test_consolidation_fixtures.py @@ -48,7 +48,9 @@ SCHASTL_FILE_NAME = "ПЕКАРНЯ СЧАСТЛИВОЧНАЯ" # в файла RB_NAME_IN_SCHASTL = "Русский бисквит" TIME_BUDGET_SECONDS = 60.0 Q1, Q2, Q3 = "Q1", "Q2", "Q3" -ROWS_TOTAL, UNMAPPED_TOTAL = 1385, 1381 # свод РБ 2024 Q3 +# свод РБ 2024 Q3; 1379 = 1381 − 2: две строки находят контрагента по ИНН, извлечённому парсером из названия +# (tabular-parser #15, golden fixtures #8; issue #33) +ROWS_TOTAL, UNMAPPED_TOTAL = 1385, 1379 CHANGED_ROWS, PROPAGATED = 4, 17 # строк свода, получивших контрагента; записей osv_entry, кроме выбранной (18 всего) SUMS = ("opening_debit", "opening_credit", "turnover_debit", "turnover_credit", "closing_debit", "closing_credit") diff --git a/api/tests/test_mapping_golden.py b/api/tests/test_mapping_golden.py index d94e47d..2c62240 100644 --- a/api/tests/test_mapping_golden.py +++ b/api/tests/test_mapping_golden.py @@ -9,13 +9,16 @@ Инварианты: строк `osv_entry` = строк результата без `TOTAL`; у каждой строки уровня > 0 есть родитель (строка того же документа с `row_number = parent_row_number`); шесть сумм равны снимку; `account_id` = строка плана счетов seed для -нормализованного кода, а для кодов вне плана — NULL (вне плана 1С остаётся только «60.АВ» синтетического снимка). +нормализованного кода, а для кодов вне плана — NULL (известные коды вне плана 1С — `KNOWN_OUT_OF_PLAN`). + +Число снимков проверяется снизу (`MIN_SNAPSHOTS`), а не на равенство (issue #33): новые снимки fixtures не ломают тест, +а проходят те же инварианты; пропажа снимков по-прежнему ловится. """ import json import time import uuid -from collections import defaultdict +from collections import Counter, defaultdict from datetime import UTC, datetime from decimal import Decimal from pathlib import Path @@ -37,7 +40,25 @@ from tests.factories import make_legal_entity, make_stored_file from tests.fixtures_helpers import golden_result GOLDEN_DIR = Path("golden") / "expected_osv_parse" -EXPECTED_SNAPSHOTS = 88 # результатов ОСВ в fixtures (rb, schastl, synthetic): 72 реальных + 16 синтетических +# результатов ОСВ в fixtures на 07.10.2026: rb 42, schastl 30, osv-dkb 22 (пакет ДКБ), synthetic 19 — всего 113 +MIN_SNAPSHOTS = 113 +# коды строк-счетов, которых нет в плане счетов seed (выгрузка 1С, issue #23): account_id у них NULL, корень счёта +# известен. Новый код вне плана валит тест — сигнал о дыре в плане счетов (follow-up arm-core #28) +KNOWN_OUT_OF_PLAN = frozenset( + { + "60.АВ", # synthetic/s09_subaccount_names + "76.07.4", # osv-dkb/npz + "76.09.1", # osv-dkb/nkz (76.09.1–76.09.4) + "76.09.2", + "76.09.3", + "76.09.4", + "76.77", # osv-dkb/primanych, osv-dkb/tsimlyansky (76.77, 76.77.1, .2, .5) + "76.77.1", + "76.77.2", + "76.77.5", + "76.АФ", # osv-dkb/primanych + } +) TIME_BUDGET_SECONDS = 60.0 # tasks 3.4: маппинг всех снимков — не дольше минуты SUM_FIELDS = ("opening_debit", "opening_credit", "turnover_debit", "turnover_credit", "closing_debit", "closing_credit") TOTAL = "TOTAL" @@ -89,10 +110,12 @@ def _check_sheet( # noqa: PLR0912 - все инварианты одного л async def test_all_golden_snapshots_mapped(seeded: AsyncSession, fixtures_dir: Path) -> None: # noqa: PLR0914 - """«Все golden-снимки парсера»: 88 результатов маппятся в БД, инварианты спеки на каждом документе, ≤ 60 с.""" + """«Все golden-снимки парсера» (не меньше 113) маппятся в БД, инварианты спеки на каждом документе, ≤ 60 с.""" session = seeded snapshots = _snapshots(fixtures_dir) - assert len(snapshots) == EXPECTED_SNAPSHOTS + groups = Counter(path.relative_to(fixtures_dir / GOLDEN_DIR).parts[0] for path in snapshots) + by_group = dict(sorted(groups.items())) + assert len(snapshots) >= MIN_SNAPSHOTS, f"снимков {len(snapshots)} < {MIN_SNAPSHOTS}: {by_group}" owner = await make_legal_entity(session, name="АО «Русский бисквит»", inn="3528052718") chart = { code: account_id for code, account_id in await session.execute(select(ChartOfAccount.code, ChartOfAccount.id)) @@ -157,8 +180,9 @@ async def test_all_golden_snapshots_mapped(seeded: AsyncSession, fixtures_dir: P f"{sorted(missing_codes)}" ) assert problems == [] - # план счетов seed = выгрузка 1С (issue #23): вне плана остаётся только «60.АВ» синтетического снимка s09 - assert missing_codes <= {"60.АВ"} + # план счетов seed = выгрузка 1С (issue #23): вне плана — только известные коды (s09 и субсчета пакета ДКБ) + unknown = sorted(missing_codes - KNOWN_OUT_OF_PLAN) + assert not unknown, f"новые коды вне плана счетов: {unknown}" assert with_kind > 0 # есть сопоставленные строки: проверка «kind ⇔ counterparty_id» не вырождена assert with_account > 0 # строки со счётом плана счетов есть — сверка account_id не вырождена assert mapping_seconds <= TIME_BUDGET_SECONDS