Files
md2gost/tests/test_layout.py
T

123 lines
4.7 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.
"""Сквозная проверка вёрстки: документ должен собираться без дефектов.
Отдельные обработчики проверяются модульными тестами, но выход текста за поле
проявляется только после сборки: он зависит от шрифта, ширины колонок и
взаимодействия пакетов. Этот тест ловит регресс, который иначе видно лишь
глазами в готовом PDF.
"""
from __future__ import annotations
import shutil
import subprocess
import tempfile
from pathlib import Path
import pytest
import md2gost
from md2gost.latex.log import parse_log
from md2gost.parser import Parser
from md2gost.render import Renderer
pytestmark = pytest.mark.skipif(
shutil.which("xelatex") is None, reason="xelatex не установлен"
)
# Документ собран из конструкций, на которых вёрстка ломалась:
# длинный токен в узкой колонке, подглава с двузначным номером в оглавлении,
# перечень сокращений, листинг с подписью и длинными строками.
FRONT_MATTER = """---
титульник: ptp-report
факультет: Информатика и системы управления (ИУ)
кафедра: Теоретическая информатика и компьютерные технологии (ИУ9)
тип: Отчёт
название: Проверка вёрстки
студент: Иванов И. И.
студент_полностью: Иванов Иван Иванович
группа: ИУ9-22Б
тип_практики: проектно-технологическая практика
предприятие: МГТУ имени Н. Э. Баумана
команда: Проверка вёрстки
хранилище: https://example.invalid/very/long/repository/path
руководитель: Петров П. П.
год: 2026
---
"""
SUBSECTIONS = "\n".join(
f"## Подглава номер {i}\n\nТекст подглавы номер {i}.\n" for i in range(1, 12)
)
BODY = f"""
# АННОТАЦИЯ
Проверка вёрстки.
# СОДЕРЖАНИЕ
# ПЕРЕЧЕНЬ ПРИНЯТЫХ СОКРАЩЕНИЙ
SDR — Software-Defined Radio — программно-определяемая радиосистема
PSO — Particle Swarm Optimisation — метод роевой оптимизации
# ВВЕДЕНИЕ
Введение.
# Раздел
{SUBSECTIONS}
Таблица 1 —— Таблица с длинным токеном
| Направление | Формат | Назначение |
| :--- | :--- | :--- |
| сервер | HackRFTestingServer:идентификатор | Приветствие, подтверждает подключение |
Листинг 1 —— Листинг с длинными строками
```cpp
template <typename Rep, typename Period>
std::vector<T> drain_with_timeout(const std::atomic<bool>& running,
const std::chrono::duration<Rep, Period>& timeout);
```
# ЗАКЛЮЧЕНИЕ
Заключение.
# СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1. Гилев, И. В. Использование технологии SDR / И. В. Гилев. – Воронеж, 2025. С. 324328.
"""
def _build(md_text: str) -> str:
"""Собрать документ и вернуть журнал xelatex."""
parser = Parser(md_text)
# Картинок в эталонном документе нет — копировать нужно только эмблему.
latex = Renderer(parser.tokens, parser.front_matter).render()
emblem = Path(md2gost.__file__).parent.parent / "emblem.png"
with tempfile.TemporaryDirectory(prefix="md2gost-layout-") as cache:
cache_dir = Path(cache)
tex = cache_dir / "doc.tex"
tex.write_text(latex, encoding="utf-8")
if emblem.is_file():
shutil.copy2(emblem, cache_dir / "emblem.png")
for _ in range(2):
subprocess.run(
["xelatex", "-interaction=nonstopmode", str(tex)],
cwd=cache_dir,
capture_output=True,
)
assert (cache_dir / "doc.pdf").is_file(), "xelatex не собрал PDF"
return (cache_dir / "doc.log").read_text(errors="replace")
def test_reference_document_has_no_layout_defects() -> None:
diags = parse_log(_build(FRONT_MATTER + BODY))
defects = [d for d in diags if d.kind in ("error", "overfull")]
assert not defects, "\n".join(f"{d.kind}: {d.message}" for d in defects)