gwoe-antragspruefer/tests/test_protokoll_parsers_hh.py
Dotty Dotter edbce27c49 test(#155): 19 Tests fuer HH-Parser
- TestNormalizeFraktionenHh: SPD, GRUENEN-Form, Linken-Form, kombinierte
  Phrasen, Doppelzaehl-Schutz
- TestParseVoteBlockHh: voller Vote-Block, ja+nein ohne enth, leerer Block,
  nur ja
- TestResolveDrucksacheHh: 'Drucksache 23/N', bare '23/N', closest-match,
  None bei keinem Treffer
- TestResultAnchorRegex: einstimmig vs. mehrheitlich, angenommen/abgelehnt
- Konstanten-Sanity: alle 5 HH-Fraktionen im Mapping abgedeckt

919 Tests gruen (+19).
2026-04-29 01:05:33 +02:00

136 lines
4.5 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.

"""Tests fuer app/protokoll_parsers/hh.py — Hamburger Beschlussprotokoll-Parser (#155).
Stichprobe-getestet gegen WP23 Sitzung 22 (Hamburg).
"""
from __future__ import annotations
import pytest
from app.protokoll_parsers.hh import (
_normalize_fraktionen_hh,
_parse_vote_block_hh,
_resolve_drucksache_hh,
RESULT_ANCHOR_RE,
ALLE_FRAKTIONEN_HH,
FRAKTIONEN_MAP_HH,
)
class TestNormalizeFraktionenHh:
def test_simple_spd(self):
assert _normalize_fraktionen_hh("der SPD") == ["SPD"]
def test_gruene_n_form(self):
assert _normalize_fraktionen_hh("der GRÜNEN") == ["GRÜNE"]
def test_die_linke(self):
assert _normalize_fraktionen_hh("der Linken") == ["LINKE"]
def test_combined_phrase(self):
result = _normalize_fraktionen_hh(
"der SPD und GRÜNEN gegen die Stimmen der CDU und AfD"
)
assert set(result) == {"SPD", "GRÜNE", "CDU", "AfD"}
def test_empty_returns_empty(self):
assert _normalize_fraktionen_hh("") == []
def test_no_double_count(self):
# 'GRÜNEN' und 'GRÜNE' beide → nur 1× GRÜNE
result = _normalize_fraktionen_hh("der GRÜNE und der GRÜNEN")
assert result.count("GRÜNE") == 1
class TestParseVoteBlockHh:
def test_full_block(self):
block = (
" mit den Stimmen der SPD und GRÜNEN "
"gegen die Stimmen der CDU und AfD "
"bei Enthaltung der Linken"
)
votes = _parse_vote_block_hh(block)
assert set(votes["ja"]) == {"SPD", "GRÜNE"}
assert set(votes["nein"]) == {"CDU", "AfD"}
assert votes["enthaltung"] == ["LINKE"]
def test_only_ja_and_nein(self):
block = (
" mit den Stimmen der SPD, GRÜNEN, CDU und Linken "
"gegen die Stimmen der AfD"
)
votes = _parse_vote_block_hh(block)
assert set(votes["ja"]) == {"SPD", "GRÜNE", "CDU", "LINKE"}
assert votes["nein"] == ["AfD"]
assert votes["enthaltung"] == []
def test_empty_block_returns_empty_lists(self):
votes = _parse_vote_block_hh("")
assert votes == {"ja": [], "nein": [], "enthaltung": []}
def test_only_ja(self):
block = " mit den Stimmen der SPD und GRÜNEN"
votes = _parse_vote_block_hh(block)
assert set(votes["ja"]) == {"SPD", "GRÜNE"}
class TestResolveDrucksacheHh:
def test_finds_ds_with_full_prefix(self):
text = "Drucksache 23/1234 ... mehrheitlich angenommen"
anchor = text.index("mehrheitlich")
assert _resolve_drucksache_hh(text, anchor) == "23/1234"
def test_finds_bare_ds_format(self):
text = "Bericht 23/3666 ... einstimmig angenommen"
anchor = text.index("einstimmig")
assert _resolve_drucksache_hh(text, anchor) == "23/3666"
def test_picks_closest(self):
text = "Drucksache 23/100 ... Drucksache 23/200 ... einstimmig angenommen"
anchor = text.index("einstimmig")
assert _resolve_drucksache_hh(text, anchor) == "23/200"
def test_returns_none_when_no_ds(self):
text = "irgendwas ... einstimmig angenommen"
anchor = text.index("einstimmig")
assert _resolve_drucksache_hh(text, anchor) is None
class TestResultAnchorRegex:
def test_einstimmig_angenommen(self):
text = "alle Empfehlungen einstimmig angenommen"
m = RESULT_ANCHOR_RE.search(text)
assert m
assert m.group("modus") == "einstimmig"
assert m.group("ergebnis") == "angenommen"
def test_mehrheitlich_with_block(self):
text = (
"Antrag mehrheitlich mit den Stimmen der SPD und GRÜNEN "
"gegen die Stimmen der CDU und AfD angenommen"
)
m = RESULT_ANCHOR_RE.search(text)
assert m
assert m.group("modus") == "mehrheitlich"
assert m.group("ergebnis") == "angenommen"
def test_mehrheitlich_abgelehnt(self):
text = (
"Antrag mehrheitlich mit den Stimmen der SPD, GRÜNEN gegen die "
"Stimmen der AfD abgelehnt"
)
m = RESULT_ANCHOR_RE.search(text)
assert m
assert m.group("ergebnis") == "abgelehnt"
class TestConstants:
def test_all_fraktionen_complete(self):
assert set(ALLE_FRAKTIONEN_HH) == {"SPD", "GRÜNE", "CDU", "AfD", "LINKE"}
def test_mapping_covers_all_fraktionen(self):
all_codes = set()
for _phrase, codes in FRAKTIONEN_MAP_HH:
all_codes.update(codes)
for f in ALLE_FRAKTIONEN_HH:
assert f in all_codes