- golden_helpers, scripts/golden_update.py (--check), test_golden на 66 ОСВ и синтетике; make golden-update/golden-check/test-fixtures - тест покрытия словарей (R-22): счётчик срабатываний Pattern; из osv_headers.yaml удалены неиспользуемые service_columns kpp/code/quantity/currency - синтетика s14–s16 в генераторе и таблице ожиданий; skip вместо падения при отсутствии osv/synthetic (T11.1); комментарий R-21 в s07 (T11.2) - линтер: предел адреса 10 вместо 4 (T3.1), обращение cell(3, 4) (T3.8); реальные файлы не фиксируют BU/RUB (T3.9) - README: golden-процесс; отмечены Task 12 и пункты 4.2, 4.3 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
"""Помощники golden-снимков: нормализация volatile-полей, путь снимка, формат записи (design D-10)."""
|
||
|
||
import json
|
||
from pathlib import Path
|
||
|
||
from golden_helpers import SNAPSHOT_DIR, golden_path, normalize_result, snapshot_text, unified_diff
|
||
|
||
|
||
def _result() -> dict:
|
||
return {
|
||
"schema_version": "1.1",
|
||
"job_id": "00000000-0000-0000-0000-000000000000",
|
||
"file_id": "00000000-0000-0000-0000-000000000000",
|
||
"service": {"name": "tabular-parser", "version": "0.1.0"},
|
||
"status": "done",
|
||
"metrics": {"duration_ms": 12, "rows": 7, "warnings": ["б", "а"]},
|
||
"documents": [{"z": 1, "a": 2}],
|
||
}
|
||
|
||
|
||
def test_normalize_removes_exactly_the_volatile_fields() -> None:
|
||
normalized = normalize_result(_result())
|
||
|
||
assert "job_id" not in normalized
|
||
assert "file_id" not in normalized
|
||
assert normalized["service"] == {"name": "tabular-parser"}
|
||
assert normalized["metrics"] == {"rows": 7, "warnings": ["б", "а"]}
|
||
assert normalized["documents"] == [{"z": 1, "a": 2}]
|
||
|
||
|
||
def test_normalize_keeps_key_and_warning_order_and_does_not_mutate_input() -> None:
|
||
source = _result()
|
||
|
||
normalized = normalize_result(source)
|
||
|
||
assert list(normalized) == ["schema_version", "service", "status", "metrics", "documents"]
|
||
assert list(normalized["documents"][0]) == ["z", "a"]
|
||
assert normalized["metrics"]["warnings"] == ["б", "а"]
|
||
assert source == _result()
|
||
|
||
|
||
def test_normalize_tolerates_missing_volatile_fields() -> None:
|
||
assert normalize_result({"status": "error"}) == {"status": "error"}
|
||
|
||
|
||
def test_golden_path_mirrors_osv_tree_without_extension(tmp_path: Path) -> None:
|
||
root = tmp_path
|
||
file = root / "osv" / "rb" / "2025-Q1" / "ОСВ сч 60.xlsx"
|
||
|
||
assert golden_path(root, file) == root / "golden" / SNAPSHOT_DIR / "rb" / "2025-Q1" / "ОСВ сч 60.json"
|
||
synthetic = root / "osv" / "synthetic" / "s01.xlsx"
|
||
assert golden_path(root, synthetic) == root / "golden" / SNAPSHOT_DIR / "synthetic" / "s01.json"
|
||
|
||
|
||
def test_golden_path_keeps_dots_inside_the_name(tmp_path: Path) -> None:
|
||
file = tmp_path / "osv" / "a" / "сч 62 за 3 квартал 2024 г..xls"
|
||
|
||
assert golden_path(tmp_path, file).name == "сч 62 за 3 квартал 2024 г..json"
|
||
|
||
|
||
def test_snapshot_text_is_utf8_json_with_indent_and_trailing_newline() -> None:
|
||
text = snapshot_text({"имя": "ОСВ", "n": ["1"]})
|
||
|
||
assert text.endswith("}\n")
|
||
assert "ОСВ" in text
|
||
assert json.loads(text) == {"имя": "ОСВ", "n": ["1"]}
|
||
assert text.startswith('{\n "имя"')
|
||
|
||
|
||
def test_unified_diff_names_files_and_shows_changed_lines() -> None:
|
||
diff = unified_diff("a\nb\n", "a\nc\n", name="снимок.json")
|
||
|
||
assert "--- снимок.json (в fixtures)" in diff
|
||
assert "+++ снимок.json (разбор сейчас)" in diff
|
||
assert "-b" in diff
|
||
assert "+c" in diff
|
||
assert unified_diff("a\n", "a\n", name="x") == ""
|