arm-tabular-parser/api/tests/fixtures/test_statements_property.py
Andrey Epifancev 07d57cbd07 test(statements): манифест реальных форм, property-тест, golden форм, покрытие словарей форм
Манифест statements_manifest.yaml по 18 реальным файлам statements-xlsx (сверен
прогоном парсера, R-13, OQ-137), property-тест по манифесту, снимки форм в
golden_helpers/golden_update/test_golden, словари форм в покрытии, синтетика
st06 для вариантов заголовков. Мёртвые записи словаря удалены (name_caption,
метки okved и okud_label) либо покрыты st06.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 20:50:25 +04:00

53 lines
2.7 KiB
Python

"""Инварианты форм на всех `../fixtures/statements-xlsx/**` по манифесту (spec «Словари форм, координаты, golden»)."""
import time
from pathlib import Path
from typing import cast
import pytest
from fixtures_helpers import statement_files
from result_contract import assert_valid_result
from statement_helpers import load_manifest, relative_key
from src.contract import FileType, ResultStatus, StatementDocument
from src.parser import get_parser
pytestmark = pytest.mark.fixtures
EXPECTED_FILES = 18
MAX_PARSE_SECONDS = 5
def test_manifest_covers_every_file(fixtures_dir: Path) -> None:
files = statement_files(fixtures_dir)
assert len(files) == EXPECTED_FILES
assert {relative_key(fixtures_dir, path) for path in files} == set(load_manifest())
def test_statement_file_matches_manifest(fixtures_dir: Path, statement_file: Path) -> None:
expectation = load_manifest()[relative_key(fixtures_dir, statement_file)]
started = time.monotonic()
file_type = cast(FileType, statement_file.suffix.lstrip(".").upper())
outcome = get_parser().parse(statement_file.read_bytes(), file_type)
assert time.monotonic() - started < MAX_PARSE_SECONDS
assert outcome.error is None, outcome.error
documents = [document for document in outcome.documents if isinstance(document, StatementDocument)]
assert [document.document_type for document in documents] == [item.type for item in expectation.documents]
all_done = all(item.status == "done" for item in expectation.documents)
assert outcome.status is (ResultStatus.DONE if all_done else ResultStatus.NEEDS_CHECK)
for document, item in zip(documents, expectation.documents, strict=True):
codes = [line.line_code for line in document.lines]
assert len(codes) == len(set(codes)), "коды уникальны"
assert all(value.column_index < len(document.columns) for line in document.lines for value in line.values)
if item.sheets:
assert document.locator.count(",") == item.sheets - 1
if item.complete:
assert document.checks is not None
assert document.checks.relations_failed == [], document.checks
assert document.columns
assert all(column.period_date is not None for column in document.columns)
if expectation.organization and document.header.organization_name is not None:
assert document.header.organization_name == expectation.organization
if expectation.inn and document.document_type not in expectation.inn_optional_for and document.header.inn:
assert document.header.inn == expectation.inn
assert_valid_result(outcome)