- header: период отдельной ячейкой (periods.yaml: standalone), тип данных отдельной ячейкой («Бухгалтерский», data_types.yaml: standalone_header), организация — хвост названия ведомости; код счёта — из первой строки-счёта таблицы (с предупреждением), если «по счету» в шапке нет. - classify/detect: текст строки может стоять правее колонки текста (колонка задаёт уровень), подписи «Код»/ «Наименование» (osv_headers.yaml: column_captions) — не группировки, строка сумм без подписи в конце таблицы — «Итого» (с предупреждением). - checks: сумма уровня 0 сверяется с «Итого» по правилу R-21 (свёрнутое сальдо «Итого» — по нетто), как у родителя. - tests: osv_dkb_files, покрытие словарей включает osv-dkb/**; README. Refs #11 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
"""Хелперы доступа к ../fixtures: каталог из ARM_KA_FIXTURES, список файлов ОСВ без синтетики, причина skip."""
|
||
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
from fixtures_helpers import (
|
||
FIXTURES_ENV,
|
||
fixtures_skip_reason,
|
||
osv_dkb_files,
|
||
osv_fixture_files,
|
||
resolve_fixtures_dir,
|
||
synthetic_files,
|
||
synthetic_skip_reason,
|
||
)
|
||
|
||
|
||
def test_env_overrides_fixtures_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
assert resolve_fixtures_dir() == tmp_path
|
||
|
||
|
||
def test_default_fixtures_dir_is_sibling_of_repository(monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.delenv(FIXTURES_ENV, raising=False)
|
||
assert resolve_fixtures_dir() == Path(__file__).resolve().parents[4] / "fixtures"
|
||
|
||
|
||
def test_no_osv_directory_gives_no_files(tmp_path: Path) -> None:
|
||
assert osv_fixture_files(tmp_path) == []
|
||
assert synthetic_files(tmp_path) == []
|
||
|
||
|
||
def test_synthetic_excluded_and_foreign_files_ignored(tmp_path: Path) -> None:
|
||
osv = tmp_path / "osv"
|
||
(osv / "rb").mkdir(parents=True)
|
||
(osv / "synthetic").mkdir()
|
||
(osv / "rb" / "b.xlsx").write_bytes(b"")
|
||
(osv / "a.xls").write_bytes(b"")
|
||
(osv / "c.xlsb").write_bytes(b"")
|
||
(osv / ".DS_Store").write_bytes(b"")
|
||
(osv / "notes.txt").write_bytes(b"")
|
||
(osv / "synthetic" / "s.xlsx").write_bytes(b"")
|
||
(osv / "synthetic" / ".gitkeep").write_bytes(b"")
|
||
(osv / "synthetic" / "README.md").write_bytes(b"")
|
||
|
||
assert osv_fixture_files(tmp_path) == [osv / "a.xls", osv / "c.xlsb", osv / "rb" / "b.xlsx"]
|
||
assert synthetic_files(tmp_path) == [osv / "synthetic" / "s.xlsx"]
|
||
|
||
|
||
def test_osv_dkb_files_skip_analysis_reports_and_hidden_files(tmp_path: Path) -> None:
|
||
dkb = tmp_path / "osv-dkb"
|
||
(dkb / "nm" / "2025-Q3").mkdir(parents=True)
|
||
(dkb / "analysis-reports").mkdir()
|
||
(dkb / "nm" / "2025-Q3" / "a.xlsx").write_bytes(b"")
|
||
(dkb / "nm" / "2025-Q3" / "~$a.xlsx").write_bytes(b"")
|
||
(dkb / "nm" / "README.md").write_bytes(b"")
|
||
(dkb / "analysis-reports" / "report.xls").write_bytes(b"")
|
||
|
||
assert osv_dkb_files(tmp_path) == [dkb / "nm" / "2025-Q3" / "a.xlsx"]
|
||
assert osv_dkb_files(tmp_path / "нет") == []
|
||
|
||
|
||
def test_hidden_and_excel_lock_files_are_ignored(tmp_path: Path) -> None:
|
||
"""T1.1: скрытые файлы и каталоги и lock-файлы Excel (`~$…`, пока книга открыта) — не фикстуры."""
|
||
osv = tmp_path / "osv"
|
||
(osv / "rb" / ".cache").mkdir(parents=True)
|
||
(osv / "synthetic").mkdir()
|
||
for path in (
|
||
osv / "rb" / "b.xlsx",
|
||
osv / "rb" / "~$b.xlsx",
|
||
osv / "rb" / ".b.xlsx",
|
||
osv / "rb" / ".cache" / "c.xlsx",
|
||
osv / "synthetic" / "s.xlsx",
|
||
osv / "synthetic" / "~$s.xlsx",
|
||
osv / "synthetic" / ".s.xls",
|
||
):
|
||
path.write_bytes(b"")
|
||
|
||
assert osv_fixture_files(tmp_path) == [osv / "rb" / "b.xlsx"]
|
||
assert synthetic_files(tmp_path) == [osv / "synthetic" / "s.xlsx"]
|
||
|
||
|
||
def test_skip_reason_mentions_env_and_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
missing = tmp_path / "нет-такого"
|
||
monkeypatch.setenv(FIXTURES_ENV, str(missing))
|
||
reason = fixtures_skip_reason()
|
||
assert reason is not None
|
||
assert FIXTURES_ENV in reason
|
||
assert str(missing) in reason
|
||
|
||
|
||
def test_skip_reason_none_when_available(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
(tmp_path / "osv").mkdir()
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
assert fixtures_skip_reason() is None
|
||
|
||
|
||
def test_synthetic_skip_reason_when_fixtures_exist_but_synthetic_is_missing_or_empty(
|
||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||
) -> None:
|
||
(tmp_path / "osv").mkdir()
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
reason = synthetic_skip_reason()
|
||
assert reason is not None
|
||
assert "osv" in reason
|
||
assert "synthetic" in reason
|
||
|
||
(tmp_path / "osv" / "synthetic").mkdir()
|
||
(tmp_path / "osv" / "synthetic" / "README.md").write_bytes(b"")
|
||
assert synthetic_skip_reason() == reason
|
||
|
||
(tmp_path / "osv" / "synthetic" / "s01.xlsx").write_bytes(b"")
|
||
assert synthetic_skip_reason() is None
|
||
|
||
|
||
def test_synthetic_skip_reason_is_none_without_fixtures(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path / "нет"))
|
||
assert synthetic_skip_reason() is None # причину тогда даёт fixtures_skip_reason
|