- test_osv_dkb.py: на каждом из 25 файлов пакета ДКБ — статусы листов по манифесту osv_dkb_expectations.yaml (данные, не if по имени файла), период по каталогу (2025-Q3, 2024-10_2025-09), структура строк, контракт, время разбора. - golden: osv-dkb/** до порога GOLDEN_MAX_BYTES = 1 МиБ (22 из 25 файлов; три файла Агрокомплекса 9–14 МБ — без снимков); golden_update, golden_helpers (подкаталог osv-dkb/), conftest (dkb_file, dkb_golden_file), хелперы. - dkb_helpers: expected_period, манифест; юнит-тесты без каталога fixtures. Stacked on #15. Closes #10 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
71 lines
3.6 KiB
Python
71 lines
3.6 KiB
Python
"""Перезапись golden-снимков разбора ОСВ и diff изменившихся (design D-10).
|
||
|
||
Из каталога `api/`: `ENV_FILE=.env.test .venv/bin/python scripts/golden_update.py [--check]` (то же — `make
|
||
golden-update`, из корня репозитория). Файлы — `fixtures/osv/**` включая `synthetic/`; снимки — в
|
||
`fixtures/golden/expected_osv_parse/` (зеркало `osv/`). Без флага снимки перезаписываются, для изменившихся печатается
|
||
unified diff; `--check` только сравнивает (код возврата 1, если снимки расходятся с разбором). Снимки части, для
|
||
которой нет исходного каталога (`osv/synthetic` отсутствует или пуст, нет реальных файлов), не удаляются.
|
||
|
||
Снимок — регрессия, а не оракул: перед коммитом в репозиторий fixtures просмотрите diff (`git -C ../fixtures diff`)
|
||
и убедитесь, что каждое изменение — следствие намеренной правки парсера.
|
||
"""
|
||
|
||
import argparse
|
||
import sys
|
||
from collections.abc import Sequence
|
||
from pathlib import Path
|
||
|
||
API_ROOT = Path(__file__).resolve().parents[1]
|
||
sys.path[:0] = [str(API_ROOT), str(API_ROOT / "tests")]
|
||
|
||
from fixtures_helpers import ( # noqa: E402
|
||
fixtures_skip_reason,
|
||
osv_dkb_golden_files,
|
||
osv_fixture_files,
|
||
resolve_fixtures_dir,
|
||
synthetic_files,
|
||
)
|
||
from golden_helpers import sync_snapshots # noqa: E402
|
||
|
||
from src.parser import get_parser # noqa: E402
|
||
|
||
EXIT_OK = 0
|
||
EXIT_DIFFERS = 1
|
||
EXIT_NO_FIXTURES = 3
|
||
|
||
|
||
def main(argv: Sequence[str] | None = None) -> int:
|
||
parser = argparse.ArgumentParser(description="Golden-снимки разбора ОСВ: перезапись + diff, либо --check")
|
||
parser.add_argument("--check", action="store_true", help="только сравнить снимки с разбором, ничего не писать")
|
||
options = parser.parse_args(argv)
|
||
|
||
reason = fixtures_skip_reason()
|
||
if reason is not None:
|
||
print(reason, file=sys.stderr)
|
||
return EXIT_NO_FIXTURES
|
||
root = resolve_fixtures_dir()
|
||
files = [*osv_fixture_files(root), *osv_dkb_golden_files(root), *synthetic_files(root)]
|
||
report = sync_snapshots(root, files, get_parser(), write=not options.check)
|
||
|
||
for diff in report.diffs:
|
||
sys.stdout.write(diff if diff.endswith("\n") else diff + "\n")
|
||
mode = "режим --check, ничего не записано" if options.check else "снимки записаны"
|
||
print(
|
||
f"файлов: {len(files)}; без изменений: {report.unchanged}; новых: {len(report.created)}; "
|
||
f"изменено: {len(report.changed)}; лишних снимков: {len(report.orphans)}; сохранено без исходного каталога: "
|
||
f"{len(report.protected)} ({mode})",
|
||
file=sys.stderr,
|
||
)
|
||
for orphan in report.orphans:
|
||
print(f"лишний снимок{'' if options.check else ' удалён'}: {orphan}", file=sys.stderr)
|
||
for kept in report.protected:
|
||
print(f"снимок сохранён (нет исходного каталога): {kept}", file=sys.stderr)
|
||
return EXIT_DIFFERS if options.check and report.differs else EXIT_OK
|
||
|
||
|
||
if __name__ == "__main__":
|
||
reconfigure = getattr(sys.stdout, "reconfigure", None)
|
||
if reconfigure is not None:
|
||
reconfigure(encoding="utf-8")
|
||
raise SystemExit(main())
|