123 lines
4.7 KiB
Python
123 lines
4.7 KiB
Python
"""Сквозная проверка вёрстки: документ должен собираться без дефектов.
|
||
|
||
Отдельные обработчики проверяются модульными тестами, но выход текста за поле
|
||
проявляется только после сборки: он зависит от шрифта, ширины колонок и
|
||
взаимодействия пакетов. Этот тест ловит регресс, который иначе видно лишь
|
||
глазами в готовом 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. – С. 324–328.
|
||
"""
|
||
|
||
|
||
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)
|