diff --git a/tests/test_protokoll_parsers_stubs.py b/tests/test_protokoll_parsers_stubs.py new file mode 100644 index 0000000..cdb0f6b --- /dev/null +++ b/tests/test_protokoll_parsers_stubs.py @@ -0,0 +1,111 @@ +"""Tests fuer die Phase-2-Stub-Parser (#106 Folge / #148-#163). + +Pro BL ein Modul `app/protokoll_parsers/.py`, das: +1. importierbar ist (Recherche-Findings im Docstring) +2. ``parse_protocol(...)`` raised ``NotImplementedError`` mit Issue-Verweis +3. **NICHT** in ``PROTOKOLL_PARSERS``-Registry registriert ist (sonst wuerde + der Auto-Ingest-Cron versuchen, sie zu nutzen und mit NotImplementedError + abbrechen) + +Diese Tests sind das Safety-Net: sobald ein Stub durch einen echten Parser +ersetzt wird, MUSS gleichzeitig der Eintrag in PROTOKOLL_PARSERS gesetzt +werden — sonst greift ``test_implemented_parsers_are_registered``. +""" +from __future__ import annotations + +import importlib + +import pytest + +from app.protokoll_parsers import PROTOKOLL_PARSERS, supported_bundeslaender + +STUB_BL_CODES = [ + "BUND", "BB", "BE", "BW", "BY", "HB", "HE", "HH", + "LSA", "MV", "NI", "RP", "SH", "SL", "SN", "TH", +] + + +@pytest.fixture(params=STUB_BL_CODES) +def stub_module(request): + code = request.param + mod_name = f"app.protokoll_parsers.{code.lower()}" + return code, importlib.import_module(mod_name) + + +class TestStubImportability: + def test_each_stub_imports(self, stub_module): + code, mod = stub_module + assert mod is not None + assert hasattr(mod, "parse_protocol") + + def test_each_stub_has_recherche_in_docstring(self, stub_module): + """Docstring enthaelt 'Recherche'-Marker und Status-Hinweis.""" + code, mod = stub_module + doc = mod.__doc__ or "" + assert "Recherche" in doc or "Status" in doc, \ + f"Stub {code}: Docstring enthaelt keine Recherche-Findings" + + def test_each_stub_links_to_issue(self, stub_module): + """Docstring verweist auf konkretes Tracking-Issue.""" + code, mod = stub_module + doc = mod.__doc__ or "" + assert "issues/" in doc, f"Stub {code}: kein Issue-Link" + + +class TestStubBehavior: + def test_each_stub_raises_not_implemented(self, stub_module): + code, mod = stub_module + with pytest.raises(NotImplementedError) as exc: + mod.parse_protocol("/dev/null") + msg = str(exc.value) + assert "noch nicht implementiert" in msg, \ + f"Stub {code}: NotImplementedError-Message ist nicht informativ" + + +class TestRegistryDiscipline: + """Sicherheitsnetz: Stubs duerfen NICHT in PROTOKOLL_PARSERS sein. + + Sobald ein Stub durch echten Parser ersetzt wird, MUSS der Implementer: + 1. NotImplementedError aus parse_protocol entfernen + 2. PROTOKOLL_PARSERS[code] = parse_protocol setzen + + Dieser Test schlaegt fehl, wenn eines der beiden vergessen wird — + explizit unten ueber test_implemented_parsers_are_registered. + """ + + def test_stubs_not_in_registry(self): + registered = set(supported_bundeslaender()) + # Aktuell muss nur NRW in der Registry sein + assert registered == {"NRW"}, ( + "Unerwartete Registry-Eintraege. Wenn neue BL implementiert sind, " + "diesen Test anpassen UND den Stub durch echten Parser ersetzen." + ) + + def test_implemented_parsers_are_registered(self, stub_module): + """Wenn ein Stub-Modul KEIN NotImplementedError mehr wirft (also + implementiert wurde), muss es in PROTOKOLL_PARSERS registriert sein. + + Dieser Test ist der Trigger: sobald der Implementer parse_protocol + echt implementiert (kein NotImplementedError mehr), schlaegt der + andere Test (test_each_stub_raises_not_implemented) fehl. Das ist + das richtige Signal — dann muessen Tests + Registry beide angepasst + werden. + """ + code, mod = stub_module + # Probe: wirft das Modul noch NotImplementedError? + try: + mod.parse_protocol("/dev/null") + implemented = True + except NotImplementedError: + implemented = False + except Exception: + # Anderer Fehler (z.B. fitz konnte /dev/null nicht oeffnen) → + # Modul ist implementiert (wuerde mit echtem PDF arbeiten) + implemented = True + + if implemented: + assert code in PROTOKOLL_PARSERS, ( + f"{code}-Parser scheint implementiert (keine NotImplementedError), " + f"aber nicht in PROTOKOLL_PARSERS registriert. Beide muessen " + f"zusammen aktualisiert werden." + )