DKB_parsers/tests/test_result_payload.py
Andrey Epifancev 6605e91838 Переименовать merge_results в result_payload, build_result вместо merge_documents
Функция не мержит, а заворачивает документы в единый конверт публикации:
одиночный документ идёт тем же путём и даёт files[] из одного элемента.
Потребителю не нужно знать, сколько документов распознал процессор.

Старые имена вводили в заблуждение на самом частом случае.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvCSGmwgL8juhZdXr32qXM
2026-09-14 14:10:31 +04:00

130 lines
4.5 KiB
Python
Raw Permalink 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.

import json
import subprocess
import sys
from pathlib import Path
import pytest
from src.core.result_payload import build_result
DOC_A = {
'file_uid': 'uid-a',
'error': {'code': '', 'message': ''},
'data_ocr': {'label': {'form_name': 'Бухгалтерский баланс'}, 'table_structure': []},
}
DOC_B = {
'file_uid': 'uid-b',
'error': {'code': '', 'message': ''},
'data_ocr': {'label': {'form_name': 'Отчёт о финансовых результатах'}, 'table_structure': []},
}
def test_single_document_keeps_the_same_envelope():
# одиночный документ проходит через ту же функцию ради единого формата
result = build_result([DOC_A], file_id='file-1', legal_entity_id='le-1')
assert result == {
'file_id': 'file-1',
'legal_entity_id': 'le-1',
'files': [DOC_A],
}
def test_several_documents_go_into_one_envelope():
result = build_result([DOC_A, DOC_B], file_id='file-1', legal_entity_id='le-1')
assert result == {
'file_id': 'file-1',
'legal_entity_id': 'le-1',
'files': [DOC_A, DOC_B],
}
def test_envelope_shape_does_not_depend_on_count():
one = build_result([DOC_A], file_id='f', legal_entity_id='l')
many = build_result([DOC_A, DOC_B], file_id='f', legal_entity_id='l')
assert list(one) == list(many)
assert isinstance(one['files'], list)
def test_does_no_io_at_all(monkeypatch):
# функция не должна ничего открывать — чтение целиком на вызывающем
def explode(*args, **kwargs):
raise AssertionError('build_result не должна трогать файловую систему')
monkeypatch.setattr('builtins.open', explode)
result = build_result([DOC_A], file_id='f', legal_entity_id='l')
assert result['files'] == [DOC_A]
def test_keeps_document_content_untouched():
# содержимое кладётся как есть: незнакомые поля и вложенность не теряются
weird = {'file_uid': 'uid-c', 'unexpected': [1, {'deep': None}], 'кириллица': 'значение'}
result = build_result([weird], file_id='file-1', legal_entity_id='le-1')
assert result['files'] == [weird]
def test_preserves_given_order():
result = build_result([DOC_B, DOC_A], file_id='f', legal_entity_id='l')
assert [doc['file_uid'] for doc in result['files']] == ['uid-b', 'uid-a']
def test_accepts_any_iterable():
# вызывающий может отдавать генератор, например потоковое чтение с шары
result = build_result((d for d in (DOC_A, DOC_B)), file_id='f', legal_entity_id='l')
assert len(result['files']) == 2
def test_rejects_empty_input():
# ноль документов — процессор ничего не распознал; это ошибка, а не пустой успех
with pytest.raises(ValueError):
build_result([], file_id='f', legal_entity_id='l')
def test_cli_reads_local_files_and_writes_result(tmp_path):
# CLI — один из вызывающих: локальное чтение живёт здесь, а не в build_result
a = tmp_path / 'doc_1.json'
a.write_text(json.dumps(DOC_A, ensure_ascii=False), encoding='utf-8')
b = tmp_path / 'doc_2.json'
b.write_text(json.dumps(DOC_B, ensure_ascii=False), encoding='utf-8')
out = tmp_path / 'result.json'
completed = subprocess.run(
[sys.executable, '-m', 'src.core.result_payload', str(a), str(b),
'--file-id', 'file-1', '--legal-entity-id', 'le-1', '-o', str(out)],
cwd=Path(__file__).resolve().parent.parent,
capture_output=True,
text=True,
)
assert completed.returncode == 0, completed.stderr
assert json.loads(out.read_text(encoding='utf-8')) == {
'file_id': 'file-1',
'legal_entity_id': 'le-1',
'files': [DOC_A, DOC_B],
}
def test_cli_handles_single_document(tmp_path):
a = tmp_path / 'doc_1.json'
a.write_text(json.dumps(DOC_A, ensure_ascii=False), encoding='utf-8')
out = tmp_path / 'result.json'
completed = subprocess.run(
[sys.executable, '-m', 'src.core.result_payload', str(a),
'--file-id', 'file-1', '--legal-entity-id', 'le-1', '-o', str(out)],
cwd=Path(__file__).resolve().parent.parent,
capture_output=True,
text=True,
)
assert completed.returncode == 0, completed.stderr
assert json.loads(out.read_text(encoding='utf-8'))['files'] == [DOC_A]