[ADD] тест вёрстки: эталонный документ собирается без выходов за поле
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
"""Сквозная проверка вёрстки: документ должен собираться без дефектов.
|
||||
|
||||
Отдельные обработчики проверяются модульными тестами, но выход текста за поле
|
||||
проявляется только после сборки: он зависит от шрифта, ширины колонок и
|
||||
взаимодействия пакетов. Этот тест ловит регресс, который иначе видно лишь
|
||||
глазами в готовом 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)
|
||||
Reference in New Issue
Block a user