119 lines
5.8 KiB
Python
119 lines
5.8 KiB
Python
|
|
"""Tests for wahlprogramme.py — registry consistency + file existence."""
|
||
|
|
from app.wahlprogramme import (
|
||
|
|
WAHLPROGRAMME,
|
||
|
|
REFERENZEN_PATH,
|
||
|
|
get_wahlprogramm,
|
||
|
|
parteien_mit_wahlprogramm,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
# Registry consistency
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
class TestRegistryStructure:
|
||
|
|
def test_active_bundeslaender_present(self):
|
||
|
|
for code in ["NRW", "LSA", "MV", "BE"]:
|
||
|
|
assert code in WAHLPROGRAMME, f"missing wahlprogramme entry for {code}"
|
||
|
|
|
||
|
|
def test_each_entry_has_required_keys(self):
|
||
|
|
required = {"file", "titel", "partei", "jahr", "seiten"}
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
missing = required - set(info.keys())
|
||
|
|
assert not missing, f"{bl}/{partei} missing keys: {missing}"
|
||
|
|
|
||
|
|
def test_jahr_is_integer(self):
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
assert isinstance(info["jahr"], int), f"{bl}/{partei} jahr not int"
|
||
|
|
|
||
|
|
def test_seiten_is_positive_integer(self):
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
assert isinstance(info["seiten"], int)
|
||
|
|
assert info["seiten"] > 0
|
||
|
|
|
||
|
|
def test_file_extension_is_pdf(self):
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
assert info["file"].endswith(".pdf")
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
# File existence — every registered file must exist on disk
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
class TestFileExistence:
|
||
|
|
"""Catches typos in the file field that would silently break embedding
|
||
|
|
indexing or PDF download links."""
|
||
|
|
|
||
|
|
def test_every_registered_pdf_exists(self):
|
||
|
|
missing = []
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
path = REFERENZEN_PATH / info["file"]
|
||
|
|
if not path.exists():
|
||
|
|
missing.append(f"{bl}/{partei}: {info['file']}")
|
||
|
|
assert not missing, "missing PDFs:\n " + "\n ".join(missing)
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
# Lookup helpers
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
class TestGetWahlprogramm:
|
||
|
|
def test_returns_dict_for_known_combination(self):
|
||
|
|
info = get_wahlprogramm("MV", "CDU")
|
||
|
|
assert info is not None
|
||
|
|
assert info["partei"] == "CDU Mecklenburg-Vorpommern"
|
||
|
|
|
||
|
|
def test_returns_none_for_unknown_bundesland(self):
|
||
|
|
assert get_wahlprogramm("XX", "CDU") is None
|
||
|
|
|
||
|
|
def test_returns_none_for_unknown_partei(self):
|
||
|
|
assert get_wahlprogramm("NRW", "BSW") is None
|
||
|
|
|
||
|
|
|
||
|
|
class TestParteienMitWahlprogramm:
|
||
|
|
def test_nrw_has_five_parteien(self):
|
||
|
|
parteien = parteien_mit_wahlprogramm("NRW")
|
||
|
|
assert len(parteien) == 5
|
||
|
|
assert set(parteien) == {"CDU", "SPD", "GRÜNE", "FDP", "AfD"}
|
||
|
|
|
||
|
|
def test_mv_has_six_parteien(self):
|
||
|
|
parteien = parteien_mit_wahlprogramm("MV")
|
||
|
|
assert set(parteien) == {"CDU", "SPD", "GRÜNE", "FDP", "AfD", "LINKE"}
|
||
|
|
|
||
|
|
def test_be_has_five_parteien(self):
|
||
|
|
parteien = parteien_mit_wahlprogramm("BE")
|
||
|
|
assert set(parteien) == {"CDU", "SPD", "GRÜNE", "LINKE", "AfD"}
|
||
|
|
|
||
|
|
def test_unknown_bundesland_empty_list(self):
|
||
|
|
assert parteien_mit_wahlprogramm("XX") == []
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
# embeddings.PROGRAMME consistency cross-check
|
||
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
class TestEmbeddingsRegistryConsistency:
|
||
|
|
"""Every entry in WAHLPROGRAMME must also exist in embeddings.PROGRAMME
|
||
|
|
so the indexer can find it. Mismatch is the kind of bug a manual smoke
|
||
|
|
misses but would show up during indexing."""
|
||
|
|
|
||
|
|
def test_every_wahlprogramm_has_embeddings_entry(self):
|
||
|
|
from app.embeddings import PROGRAMME
|
||
|
|
|
||
|
|
# Build expected programm_id from filename: "cdu-mv-2021.pdf" → "cdu-mv-2021"
|
||
|
|
missing = []
|
||
|
|
for bl, parteien in WAHLPROGRAMME.items():
|
||
|
|
for partei, info in parteien.items():
|
||
|
|
pid = info["file"].rsplit(".", 1)[0]
|
||
|
|
if pid not in PROGRAMME:
|
||
|
|
missing.append(f"{bl}/{partei} → {pid}")
|
||
|
|
assert not missing, (
|
||
|
|
"WAHLPROGRAMME entries missing in embeddings.PROGRAMME:\n "
|
||
|
|
+ "\n ".join(missing)
|
||
|
|
)
|