arm-tabular-parser/api/tests/unit/test_config.py
Andrey Epifancev e705d75520 feat(parser): контрольные суммы §1.4, статусы, OsvParser как парсер по умолчанию, лимиты
checks.py: тождество сальдо по каждой строке, суммы родителя = Σ детей того же data_type
(CURRENCY/QUANTITY исключены; обороты — по колонкам, сальдо — по колонкам или по нетто при
свёрнутом сальдо родителя), «Итого» = корневой счёт (R-13: нет корня — «Итого» пусто/0;
R-20: нет «Итого» — false и предупреждение).
osv.py: OsvParser — лимит размера, чтение по сигнатуре, листы по содержимому (формы ББ/ОФР и
прочие — пропуск с предупреждением), карта исходов D-6, кооперативный дедлайн, metrics
(rows без TOTAL, warnings с «sheet=<имя> hierarchy=<стратегия>» первой записью по листу).
get_parser(settings, rules_dir=…) → OsvParser (словари грузятся при создании: битый словарь —
падение старта); PARSE_MAX_BYTES / PARSE_TIMEOUT_SECONDS в Settings и .env.*; app.py передаёт
настройки. test_null_parser.py → test_parser_factory.py.
Тесты: юнит-карта статусов, «Испорченная сумма», «Пустая ОСВ», два листа ОСВ, новый синоним
без релиза кода (R-8); property-тест на 66 реальных файлах (все done, < 5 с, схема v1.1).
test_app и интеграционный round-trip ждут ошибку реального парсера вместо NOT_IMPLEMENTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 14:37:21 +04:00

51 lines
2.4 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.

"""Unit-тесты настроек `src/core/config.py` (spec «Старт с минимальным окружением»; R-35)."""
from collections.abc import Callable
import pytest
from pydantic import ValidationError
from src.core.config import Settings
SettingsFactory = Callable[..., Settings]
def test_minimal_environment_gives_defaults(minimal_settings: SettingsFactory) -> None:
settings = minimal_settings()
assert settings.DEBUG is True
assert settings.OPENBAO.MINIO.MINIO_BUCKET == "arm-ka"
assert settings.OPENBAO.NATS.NATS_URL == "nats://localhost:4222"
assert settings.OPENBAO.NATS.NATS_SEED == ""
assert settings.OPENBAO.NATS.NATS_JWT == ""
assert settings.NATS_ENABLED is True
assert settings.SERVICE_NAME == "tabular-parser"
assert settings.WORKER_CONCURRENCY == 1
assert settings.PUBLISH_RETRIES == 3 # noqa: PLR2004 - значение по умолчанию из spec
assert settings.DONE_CACHE_SIZE == 1000 # noqa: PLR2004 - значение по умолчанию из spec
assert settings.PARSE_MAX_BYTES == 50 * 1024 * 1024 # design D-8: 50 МиБ
assert settings.PARSE_TIMEOUT_SECONDS == 120 # noqa: PLR2004 - значение по умолчанию из design D-8
def test_parse_limits_must_be_positive(minimal_settings: SettingsFactory) -> None:
with pytest.raises(ValidationError, match="PARSE_MAX_BYTES"):
minimal_settings("PARSE_MAX_BYTES=0\n")
with pytest.raises(ValidationError, match="PARSE_TIMEOUT_SECONDS"):
minimal_settings("PARSE_TIMEOUT_SECONDS=0\n")
def test_publish_retries_zero_is_allowed(minimal_settings: SettingsFactory) -> None:
"""0 — без повторов: одна попытка публикации (NatsConnection принимает publish_retries ≥ 0)."""
assert minimal_settings("PUBLISH_RETRIES=0\n").PUBLISH_RETRIES == 0
def test_publish_retries_negative_is_rejected(minimal_settings: SettingsFactory) -> None:
with pytest.raises(ValidationError, match="PUBLISH_RETRIES"):
minimal_settings("PUBLISH_RETRIES=-1\n")
def test_service_name_other_than_contract_value_is_rejected(minimal_settings: SettingsFactory) -> None:
"""SERVICE_NAME — `service.name` конвертов контракта: другое значение — ошибка конфигурации при старте."""
with pytest.raises(ValidationError, match="SERVICE_NAME"):
minimal_settings("SERVICE_NAME=scan-gateway\n")