test(#134): wahlprogramm_fetch Coverage 42.8% → 54.4%
8 zusaetzliche Tests: - TestLockFileRobustness: kaputtes JSON, fehlende Datei, _save_lock-Roundtrip - TestLoadLinks: missing yaml + empty yaml (gestubbed) - TestGetMissingProgrammes: leere/gefuellte Eintraege, Bundesland-Filter yaml ist im Unit-Setup gestubbed; Tests patchen _load_links direkt statt echte YAML-Parsing zu erzwingen — die echte Datei-Validierung gehoert in die integration-Suite gegen die produktive links.yaml.
This commit is contained in:
parent
8f3a811a83
commit
722b073bbd
@ -300,6 +300,88 @@ class TestShaLock:
|
|||||||
assert lock["spd-mv.pdf"] == _sha(content)
|
assert lock["spd-mv.pdf"] == _sha(content)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Test 5: Lock-File und YAML-Robustheit (#134 Coverage-Backfill)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestLockFileRobustness:
|
||||||
|
def test_corrupt_lock_file_returns_empty_dict(self, tmp_path):
|
||||||
|
"""Kaputtes JSON darf den Caller nicht crashen — leeren Lock liefern."""
|
||||||
|
from app.wahlprogramm_fetch import _load_lock
|
||||||
|
bad = tmp_path / "broken-lock.json"
|
||||||
|
bad.write_text("{ this is not json ;)")
|
||||||
|
with patch("app.wahlprogramm_fetch._LOCK_FILE", bad):
|
||||||
|
result = _load_lock()
|
||||||
|
assert result == {}
|
||||||
|
|
||||||
|
def test_missing_lock_file_returns_empty_dict(self, tmp_path):
|
||||||
|
from app.wahlprogramm_fetch import _load_lock
|
||||||
|
missing = tmp_path / "no-such-file.json"
|
||||||
|
with patch("app.wahlprogramm_fetch._LOCK_FILE", missing):
|
||||||
|
assert _load_lock() == {}
|
||||||
|
|
||||||
|
def test_save_lock_writes_valid_json(self, tmp_path):
|
||||||
|
from app.wahlprogramm_fetch import _save_lock
|
||||||
|
target = tmp_path / "lock.json"
|
||||||
|
with patch("app.wahlprogramm_fetch._LOCK_FILE", target):
|
||||||
|
_save_lock({"x.pdf": "abc123", "y.pdf": "def456"})
|
||||||
|
import json
|
||||||
|
loaded = json.loads(target.read_text())
|
||||||
|
assert loaded == {"x.pdf": "abc123", "y.pdf": "def456"}
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoadLinks:
|
||||||
|
def test_missing_yaml_returns_empty(self, tmp_path):
|
||||||
|
from app.wahlprogramm_fetch import _load_links
|
||||||
|
with patch("app.wahlprogramm_fetch._LINKS_FILE", tmp_path / "missing.yaml"):
|
||||||
|
assert _load_links() == {}
|
||||||
|
|
||||||
|
def test_empty_yaml_returns_empty(self, tmp_path):
|
||||||
|
from app.wahlprogramm_fetch import _load_links
|
||||||
|
target = tmp_path / "empty.yaml"
|
||||||
|
target.write_text("")
|
||||||
|
with patch("app.wahlprogramm_fetch._LINKS_FILE", target):
|
||||||
|
assert _load_links() == {}
|
||||||
|
|
||||||
|
# Hinweis: yaml ist im Unit-Setup gestubbed (siehe Top-of-File), deshalb
|
||||||
|
# testen wir _load_links nur mit existing-vs-missing-File. Die echte
|
||||||
|
# YAML-Parsing-Logik wird in der integration-Suite gegen die echte
|
||||||
|
# links.yaml validiert.
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetMissingProgrammes:
|
||||||
|
"""Tests fuer get_missing_programmes — listet BL/Partei-Kombinationen mit
|
||||||
|
Kandidaten-URL aber fehlender lokaler Datei. yaml ist gestubbed; Tests
|
||||||
|
patchen daher _load_links direkt."""
|
||||||
|
|
||||||
|
def test_no_yaml_returns_empty(self):
|
||||||
|
from app.wahlprogramm_fetch import get_missing_programmes
|
||||||
|
with patch("app.wahlprogramm_fetch._load_links", return_value={}):
|
||||||
|
assert get_missing_programmes() == []
|
||||||
|
|
||||||
|
def test_lists_entries_when_file_missing(self, tmp_path):
|
||||||
|
"""Eintrag in YAML, registriertes WAHLPROGRAMME-File fehlt → listed."""
|
||||||
|
from app.wahlprogramm_fetch import get_missing_programmes
|
||||||
|
fake_links = {"BX": {"XYZ": [{"url": "https://example.com/x.pdf"}]}}
|
||||||
|
with patch("app.wahlprogramm_fetch._load_links", return_value=fake_links):
|
||||||
|
with patch("app.wahlprogramm_fetch._REFERENZEN_DIR", tmp_path / "ref"):
|
||||||
|
missing = get_missing_programmes()
|
||||||
|
codes = [m["bl"] for m in missing]
|
||||||
|
assert "BX" in codes
|
||||||
|
|
||||||
|
def test_bundesland_filter(self, tmp_path):
|
||||||
|
from app.wahlprogramm_fetch import get_missing_programmes
|
||||||
|
fake_links = {
|
||||||
|
"BX": {"XYZ": [{"url": "https://example.com/x.pdf"}]},
|
||||||
|
"BY": {"ABC": [{"url": "https://example.com/y.pdf"}]},
|
||||||
|
}
|
||||||
|
with patch("app.wahlprogramm_fetch._load_links", return_value=fake_links):
|
||||||
|
with patch("app.wahlprogramm_fetch._REFERENZEN_DIR", tmp_path / "ref"):
|
||||||
|
missing = get_missing_programmes(bundesland="BX")
|
||||||
|
codes = {m["bl"] for m in missing}
|
||||||
|
assert codes == {"BX"}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Test 4: og_card — cache_key Determinismus und Cache-Miss/Hit
|
# Test 4: og_card — cache_key Determinismus und Cache-Miss/Hit
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user