Ctrl K
ComunidadGuías…

tests/test_literature_check_report.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""
End-to-end test of the bibliography check report: parse → database lookup
→ field comparison → report, with a fake LLM and fake databases. Runs the
report in English and in German (output-language catalog).
"""

import asyncio
import json

import pytest

from src import output_language
from src.connectors.literature_apis import LiteratureAPIClient
from src.pipeline.literature_check import LiteratureChecker

RAW = """Smith, J. (2020). Deep learning for bibliographies. Journal of Tests, 12(3), 1-10.

Doe, A. (2019). A paper nobody can find. Unknown Press."""

PARSED = [
    {"raw_text": "Smith, J. (2020). Deep learning for bibliographies.", "authors": ["Smith, J."],
     "title": "Deep learning for bibliographies", "year": "2020", "journal": "Journal of Tests",
     "volume": "12", "issue": "3", "pages": "1-10", "entry_type": "article"},
    {"raw_text": "Doe, A. (2019). A paper nobody can find.", "authors": ["Doe, A."],
     "title": "A paper nobody can find", "year": "2019", "entry_type": "book"},
]


class FakeLLM:
    async def primary_complete(self, messages, **kw):
        text = messages[-1]["content"]
        if "Context:" in text:
            return "Harmless formatting difference."
        return json.dumps(PARSED)

    def get_usage_stats(self):
        return {"total_requests": 2, "total_tokens": 100}


class FakeAPIs(LiteratureAPIClient):
    def __init__(self):
        super().__init__()

    async def lookup_entry(self, entry):
        if entry.title.startswith("Deep"):
            return [{"source": "crossref", "title": "Deep learning for bibliographies",
                     "authors": ["John Smith"], "year": "2021", "journal": "Journal of Tests",
                     "doi": "10.1000/test", "cited_by_count": 42}]
        return []


def _run(lang):
    checker = LiteratureChecker(FakeLLM(), searxng=None, lang=lang)
    checker.api_client = FakeAPIs()
    async def progress(*args, **kwargs):
        pass
    markdown, report = asyncio.run(checker.check(raw_text=RAW, progress_callback=progress))
    asyncio.run(checker.close())
    return markdown, report


def test_report_in_english():
    md, report = _run("en")
    assert report.total == 2
    assert "# Bibliography check report" in md
    assert "Entries checked" in md
    assert "Year" in md                     # deviation 2020 → 2021, field label
    assert "Corrected bibliography (APA)" in md
    assert "Prüfbericht" not in md


@pytest.fixture
def german(monkeypatch):
    monkeypatch.setenv("OUTPUT_LANGUAGES", "en,de")
    output_language.reload()
    yield
    monkeypatch.delenv("OUTPUT_LANGUAGES")
    output_language.reload()


def test_report_in_german(german):
    md, _ = _run("de")
    assert "# Prüfbericht Literaturverzeichnis" in md
    assert "Geprüfte Einträge" in md
    assert "Jahr" in md
    assert "Korrigiertes Literaturverzeichnis (APA)" in md


def test_llm_failure_is_not_reported_as_a_format_problem():
    """If the model cannot be reached, the message says so — not 'check the format'."""
    class BrokenLLM(FakeLLM):
        async def primary_complete(self, messages, **kw):
            raise ConnectionError("Connection error.")

    checker = LiteratureChecker(BrokenLLM(), searxng=None, lang="en")
    checker.api_client = FakeAPIs()

    async def progress(*args, **kwargs):
        pass
    md, report = asyncio.run(checker.check(raw_text=RAW, progress_callback=progress))
    asyncio.run(checker.close())
    assert report.total == 0
    assert "language model returned an error" in md and "Connection error" in md
    assert "check the format" not in md