refactor(gost): вынести сборку списка литературы в app.bibliography + 7 тестов

Сортировка (кириллица→латиница), нумерация и выбор форматтера жили внутри
Celery-задачи с БД и не тестировались — хотя это порядок и вид готового списка
литературы, который видит студент. Вынес в чистый app.bibliography.build_bibliography:

- нумерация сквозная с 1; total = число записей;
- сортировка по фамилии первого автора, кириллица раньше латиницы;
- стиль 7.1 → полное описание (format_full), иначе 7.0.5 → краткая ссылка;
- doc_id сохраняется в каждой записи; пустой список → total 0.

ORM→dict конверсия осталась в задаче (она из БД), поведение сохранено 1:1.
Добавлен в mypy-гейт. Тестов всего: 73 (indexer 24, gost 24, gpu 25).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-08-11 20:20:01 +05:00
parent b2d2061a83
commit ccc3521e74
4 changed files with 106 additions and 28 deletions

View File

@@ -0,0 +1,59 @@
"""Юнит-тесты сборки списка литературы по ГОСТ (порядок и нумерация)."""
from app.bibliography import build_bibliography
def _doc(doc_id: int, last_name: str, year: int = 2020) -> dict:
return {
"id": doc_id,
"title": "Некоторое название работы",
"authors": [{"last_name": last_name}],
"year": year,
"journal": "Вестник",
"lang": "ru",
}
def test_empty_list():
out = build_bibliography([], style="7.1")
assert out == {"bibliography": [], "style": "7.1", "total": 0}
def test_numbering_is_sequential_from_one():
docs = [_doc(10, "Борисов"), _doc(20, "Александров"), _doc(30, "Васильев")]
out = build_bibliography(docs, style="7.1")
assert [b["number"] for b in out["bibliography"]] == [1, 2, 3]
assert out["total"] == 3
def test_sorted_alphabetically_within_cyrillic():
docs = [_doc(1, "Яковлев"), _doc(2, "Абрамов"), _doc(3, "Миронов")]
out = build_bibliography(docs, style="7.1")
order = [b["doc_id"] for b in out["bibliography"]]
assert order == [2, 3, 1] # Абрамов, Миронов, Яковлев
def test_cyrillic_sorted_before_latin():
docs = [_doc(1, "Adams"), _doc(2, "Яковлев")]
out = build_bibliography(docs, style="7.1")
# русский источник идёт первым, иностранный — после
assert [b["doc_id"] for b in out["bibliography"]] == [2, 1]
def test_style_7_1_uses_full_citation():
out = build_bibliography([_doc(1, "Иванов")], style="7.1")
citation = out["bibliography"][0]["citation"]
assert "//" in citation # полное описание статьи содержит разделитель журнала
assert out["style"] == "7.1"
def test_style_7_0_5_uses_short_citation():
out = build_bibliography([_doc(1, "Иванов", year=2021)], style="7.0.5")
citation = out["bibliography"][0]["citation"]
assert citation == "[Иванов, 2021]" # краткая ссылка
assert out["style"] == "7.0.5"
def test_doc_id_preserved_in_each_entry():
out = build_bibliography([_doc(42, "Иванов"), _doc(7, "Абрамов")], style="7.1")
assert {b["doc_id"] for b in out["bibliography"]} == {42, 7}