arm-scan-gateway/api/tests/golden_update.py

75 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Golden нормализатора: сбор склейки реального ответа и запись эталонов (`make golden-update`).
Набор задания `<name>` — `<name>.json` + `<name>_*.json` из `../fixtures/ocr` (как у эмулятора); эталон —
`../fixtures/ocr/expected_normalize/<name>.json`. Запуск: `cd api && .venv/bin/python -m tests.golden_update`.
"""
import json
import sys
from pathlib import Path
from typing import Any
from arm_statements import default_rules
from src.gateway.hotfolder import AnswerFile
from src.gateway.merge import merge_answers
from src.normalizer import NormalizeOutcome, OcrNormalizer
API_DIR = Path(__file__).resolve().parents[1]
REAL_FIXTURES = API_DIR.parent.parent / "fixtures" / "ocr"
GOLDEN_DIR = REAL_FIXTURES / "expected_normalize"
JOB = "3f1c2b7a-0000-4000-8000-000000000001"
GOLDEN_VERSION = "0" * 40 # фиксированная версия копии: golden от раскладки копии не зависит
def golden_cases() -> list[str]:
"""Имена `<name>` без суффикса `_*`: `aep_3`, `aep_6`, … (по одному на набор)."""
names = sorted(p.name[: -len(".json")] for p in REAL_FIXTURES.glob("*.json") if p.is_file())
stems = {name for name in names if not any(name.startswith(f"{other}_") for other in names if other != name)}
return sorted(stems)
def real_set(name: str) -> dict[str, Any]:
files = []
for path in sorted(REAL_FIXTURES.glob(f"{name}*.json")):
base = path.name[: -len(".json")]
if base == name:
target = f"{JOB}.json"
elif base.startswith(f"{name}_"):
target = f"{JOB}_{base[len(name) + 1 :]}.json"
else:
continue
files.append(AnswerFile(target, path.read_bytes()))
return dict(merge_answers(JOB, files))
def outcome_to_json(outcome: NormalizeOutcome) -> dict[str, Any]:
return {
"status": outcome.status.value,
"warnings": [w.to_wire() for w in outcome.warnings],
"metrics": outcome.metrics.model_dump(mode="json", exclude_none=True) if outcome.metrics else None,
"error": outcome.error.model_dump(mode="json", exclude_none=True) if outcome.error else None,
"documents": [doc.model_dump(mode="json", exclude_none=True) for doc in outcome.documents],
}
def main() -> int:
if not REAL_FIXTURES.is_dir():
print(f"нет каталога {REAL_FIXTURES}", file=sys.stderr)
return 2
rules = default_rules()
GOLDEN_DIR.mkdir(exist_ok=True)
for name in golden_cases():
payload = outcome_to_json(OcrNormalizer(rules, version=GOLDEN_VERSION).normalize(real_set(name)))
(GOLDEN_DIR / f"{name}.json").write_text(
json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
print(
f"{name}: {payload['status']}, документов {len(payload['documents'])}, "
f"предупреждений {len(payload['warnings'])}"
)
return 0
if __name__ == "__main__":
sys.exit(main())