Files
anti-plagiarism/services/worker-gost/tests/test_gost_7_1.py
jze9 ecc10a4413 test: юнит-суит L1/L2/L3 + ГОСТ (41 тест) и гейт в CI перед деплоем
Первый настоящий автоматический тест-суит проекта — раньше регрессии ловились
руками. Покрыта чистая логика детекции и форматирования (без БД/Redis/GPU/Ollama):

- worker-indexer: L1 Winnowing (точные совпадения, идемпотентность отпечатка,
  диапазон signed int64) и L2 MinHash LSH (шинглы, Jaccard, near-duplicate +
  upsert через in-memory-фолбэк).
- worker-gpu: L3 FAISS — возврат doc_id из PostgreSQL (IndexIDMap2),
  идемпотентность add_vectors (remove-before-add, без дублей), self-match ≈ 1,
  ранжирование. Прямо стережёт баги, из-за которых индекс переписывался.
- worker-gost: ГОСТ 7.1-2003 и 7.0.5-2008 — авторы (≤3 / 4+ «и др.»/et al.),
  статья/книга/web, DOI, порядок сортировки кириллица→латиница, стр. в ссылке.

Обвязка: per-service pytest.ini/conftest/requirements-test. scripts/run_tests.sh
гоняет тесты в изолированных python:3.11-slim контейнерах (не засоряя хост),
через Tsinghua-зеркало. CI: job `test` теперь гейтит `deploy` (needs: test) —
падение тестов блокирует прод-деплой. make test / make test-one SVC=...

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 17:11:08 +05:00

81 lines
2.6 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.
"""Юнит-тесты полного библиографического описания по ГОСТ 7.1-2003."""
from app.formatters.gost_7_1 import (
GOST71Formatter,
_format_author,
_format_authors,
_get_sort_key,
format_full,
)
def test_author_with_initials():
assert _format_author({"last_name": "Иванов", "initials": "И. И."}) == "Иванов И. И."
def test_author_initials_get_trailing_dot():
assert _format_author({"last_name": "Иванов", "initials": "И. И"}) == "Иванов И. И."
def test_author_from_first_name():
assert (
_format_author({"last_name": "Петров", "first_name": "Пётр Петрович"})
== "Петров П.П."
)
def test_author_last_name_only():
assert _format_author({"last_name": "Сидоров"}) == "Сидоров"
def test_author_empty():
assert _format_author({}) == ""
def test_authors_up_to_three_all_listed():
authors = [{"last_name": "А"}, {"last_name": "Б"}, {"last_name": "В"}]
assert _format_authors(authors) == "А, Б, В"
def test_authors_four_plus_truncated_ru():
authors = [{"last_name": n} for n in ("А", "Б", "В", "Г")]
assert _format_authors(authors, lang="ru") == "А, Б, В, и др."
def test_authors_four_plus_truncated_en():
authors = [{"last_name": n} for n in ("A", "B", "C", "D")]
assert _format_authors(authors, lang="en") == "A, B, C, et al."
def test_article_has_journal_year_and_doi():
doc = {
"title": "Заголовок статьи",
"journal": "Вестник науки",
"year": 2023,
"volume": "5",
"issue": "2",
"pages": "10-20",
"doi": "10.1234/abc",
"authors": [{"last_name": "Иванов", "initials": "И.И."}],
}
out = format_full(doc)
assert out.startswith("Иванов И.И.. Заголовок статьи")
assert "// Вестник науки" in out
assert "— 2023" in out
assert "Т. 5" in out and "№ 2" in out
assert "С. 10-20" in out
assert out.endswith("DOI: 10.1234/abc")
def test_web_resource_marked_and_has_url():
doc = {"title": "Портал", "url": "https://example.org", "year": 2024}
out = GOST71Formatter().format_full(doc)
assert "[Электронный ресурс]" in out
assert "URL: https://example.org" in out
def test_sort_key_cyrillic_before_latin():
ru = _get_sort_key({"authors": [{"last_name": "Яковлев"}]})
en = _get_sort_key({"authors": [{"last_name": "Adams"}]})
assert ru < en # кириллица (префикс 0) сортируется раньше латиницы (префикс 1)