+'To run tests.'
+# built-ins
+from sys import exit as sys_exit
+from pathlib import Path
+from typing import Optional
+# requirements.txt
+from jinja2 import (Environment as JinjaEnv,
+ FileSystemLoader as JinjaFSLoader)
+# ourselves
+from ledgplom.http import PAGENAME_LEDGER_STRUCTURED, PATH_TEMPLATES
+from ledgplom.ledger import Ledger
+
+
+_EXT_DAT = '.dat'
+_EXT_HTML = '.html'
+_PATH_TESTS = Path('tests')
+
+
+def run_tests() -> None:
+ 'Run tests from tests directory.'
+ def fail(abort_msg: str, msg_prefix: str, idx: Optional[int]) -> None:
+ for jdx, line in enumerate(lines_rendered[:idx], start=1):
+ print(f'{jdx}: [{line}]')
+ print(f'{msg_prefix} FAILED – {abort_msg}')
+ sys_exit(1)
+
+ jinja = JinjaEnv(loader=JinjaFSLoader(PATH_TEMPLATES), autoescape=True)
+ tmpl = jinja.get_template(f'{PAGENAME_LEDGER_STRUCTURED}.tmpl')
+ for path in [p for p in _PATH_TESTS.iterdir()
+ if p.parts[-1].endswith(_EXT_DAT)]:
+ with Path(str(path)[:-len(_EXT_DAT)] + _EXT_HTML
+ ).open('r', encoding='utf8') as f:
+ lines_expected = [line.rstrip('\n') for line in f.readlines()]
+ lines_rendered = tmpl.render(blocks=Ledger(path).blocks).split('\n')
+ msg_prefix = f'test for {path}:'
+ for idx0, line in enumerate(lines_rendered):
+ idx1 = idx0 + 1
+ abort_msg = ''
+ if idx1 > len(lines_expected):
+ abort_msg = f'only {idx0} lines expected'
+ elif lines_expected[idx0] != line:
+ abort_msg = f'line differs, expected: [{lines_expected[idx0]}]'
+ if abort_msg:
+ fail(abort_msg, msg_prefix, idx1)
+ if len(lines_expected) > idx1:
+ fail(f'more lines expected line {idx1}', msg_prefix, None)
+ print(f'{msg_prefix} passed')