gwoe-antragspruefer/tests/integration/ground_truth.py
Dotty Dotter 15b9af8795 Sub-B: NRW Sample 10/5376 — F.D.P.+CDU CO2-Minderungsprogramm 1990
Letzter offener Sub-B-Sample-Slot. NRW liefert ein historisches WP10-
Sample (28.03.1990, F.D.P.+CDU-Entschließung zum NRW-CO2-Minderungs-
programm) — interessant für die GWÖ-Bilanzierung als Beleg, dass
Klimaschutz seit 35 Jahren auf dem Tisch liegt.

NRWAdapter.get_document() konstruiert die PDF-URL deterministisch über
das MMD{wp}-{nummer}.pdf-Schema, das auch für historische Wahlperioden
funktioniert (HEAD 200 verifiziert). Die Title/Fraktionen/Datum-Felder
bleiben für historische WPs leer, weil der Adapter sie aus der OPAL-
Suche nicht extrahiert (die nur die aktuelle WP18 indexiert). Der
Sample-Eintrag prüft daher nur existence + URL-Schema, beides wird vom
Sub-B-Test honoriert (leere Felder werden geskipped).

Sub-B im Container: 10/10 grün (vorher 9/9 mit NRW als skip).

Refs: #52, #59 (Sub-B Live-Verifikation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:43:17 +02:00

173 lines
8.1 KiB
Python

"""Manuell kuratierte Drucksachen pro aktivem Bundesland.
Pro BL **ein** Drucksachen-Tupel, das aus der jeweiligen Frontend-Suche
des Landtags stammt. Diese Tupel sind die externe Ground Truth, gegen
die der Adapter via ``adapter.get_document(...)`` gespiegelt wird
(siehe ``test_frontend_xref.py``, Sub-Issue B).
## Wartung
Wenn ein Test in ``test_frontend_xref.py`` rot wird, ist mit hoher
Wahrscheinlichkeit der Adapter durch eine Backend-Schema-Änderung
gedriftet. Der Wartende soll dann:
1. ``frontend_search_url`` öffnen
2. Die Drucksache `drucksache` dort suchen
3. Felder gegen das ``GroundTruth``-Tupel hier abgleichen
4. Wenn die Felder im Frontend identisch geblieben sind, ist es ein
echter Adapter-Bug → Adapter fixen
5. Wenn das Frontend selbst sich geändert hat (z.B. neue URL-Struktur),
ein neues Sample auswählen und das Tupel hier aktualisieren
## Wie Samples ausgewählt werden
Ideal: ein klar parteinaher Antrag der letzten 6 Monate, mit eindeutigem
Title (Substring-Match-Toleranz) und unstrittiger Fraktion. Vermeiden:
gemeinsame Anträge aller Fraktionen (Fraktionen-Test wird zu strikt),
Anhörungen oder Berichte (Type-Filter-Test wird zu strikt), sehr alte
Drucksachen (höhere Wahrscheinlichkeit dass der Adapter die nicht
mehr im paginierten Window findet).
"""
from dataclasses import dataclass, field
@dataclass
class GroundTruth:
"""Ein bekanntes Drucksache-Tupel als externe Ground Truth."""
bundesland: str
drucksache: str # z.B. "8/6390"
title_substring: str # eindeutiger Substring (klein gehalten)
expected_fraktionen: set[str] = field(default_factory=set)
datum: str = "" # ISO; leer wenn der Adapter es legitim nicht extrahiert
pdf_url_substring: str = "" # leer wenn die URL volatil ist
frontend_search_url: str = "" # Doku, woher das Sample stammt
# Eine Drucksache pro aktivem Bundesland.
# Stand: 2026-04-09. Bei Drift bitte das Sample ersetzen, nicht löschen.
GROUND_TRUTH: list[GroundTruth] = [
# ─── NRW (OPAL) ─────────────────────────────────────────────────────
# NRW-Drucksachen folgen dem MMD{wp}-{nummer}.pdf-URL-Schema, das auch
# für historische Wahlperioden funktioniert. Sample 10/5376 vom
# 28.03.1990 (WP10) ist ein F.D.P.+CDU-Entschließungsantrag zum
# NRW-CO2-Minderungsprogramm — historisch interessant für die GWÖ-
# Bilanzierung (Klimaschutz seit 1990) und garantiert stabil im
# Archiv. NRWAdapter.get_document liefert für historische WPs nur
# existence + URL — title/fraktionen/datum bleiben leer, deshalb sind
# die Sample-Felder hier auf das Minimum reduziert.
GroundTruth(
bundesland="NRW",
drucksache="10/5376",
title_substring="Drucksache 10/5376", # Stub-title des Adapters
pdf_url_substring="MMD10-5376",
frontend_search_url="https://opal.landtag.nrw.de",
),
# ─── MV (ParlDok 8.x) ───────────────────────────────────────────────
GroundTruth(
bundesland="MV",
drucksache="8/6390",
title_substring="Krisenmechanismus",
expected_fraktionen={"CDU"},
datum="2026-03-18",
pdf_url_substring="dokument/",
frontend_search_url="https://www.dokumentation.landtag-mv.de/parldok/",
),
# ─── BE (PARDOK / portala) ──────────────────────────────────────────
# Sample muss eine BE-Drucksache sein, die vom PortalaAdapter
# zuverlässig in den top results gelistet wird (search-Pagination
# ist BE-eigen und liefert nicht alle WP19-Anträge zurück).
# 19/2606 ist eine etablierte GRÜNE-Drucksache mit klarer Title-
# Substring "Menstruation".
GroundTruth(
bundesland="BE",
drucksache="19/2606",
title_substring="Menstruation",
expected_fraktionen={"GRÜNE"},
datum="2025-07-22",
pdf_url_substring="pardok.parlament-berlin.de",
frontend_search_url="https://pardok.parlament-berlin.de/portala/",
),
# ─── LSA (PADOKA / portala) ─────────────────────────────────────────
GroundTruth(
bundesland="LSA",
drucksache="8/6726",
title_substring="Demokratie beginnt im Klassenzimmer",
expected_fraktionen={"GRÜNE"},
datum="2026-03-06",
pdf_url_substring="d6726",
frontend_search_url="https://padoka.landtag.sachsen-anhalt.de/portal/",
),
# ─── BW (PARLIS / portala-Variante) ─────────────────────────────────
# BW kodiert den Underscore in der PDF-URL als %5F (z.B.
# "17%5F10323.pdf"), deshalb ist das URL-Substring-Pattern hier
# %5F-getrennt — `17_10323` würde nicht matchen.
GroundTruth(
bundesland="BW",
drucksache="17/10323",
title_substring="Arbeitsbedingungen",
expected_fraktionen={"GRÜNE"},
datum="2026-03-16",
pdf_url_substring="17%5f10323",
frontend_search_url="https://parlis.landtag-bw.de/parlis/",
),
# ─── HH (ParlDok 8.x) ───────────────────────────────────────────────
GroundTruth(
bundesland="HH",
drucksache="23/3700",
title_substring="Stadtteilklinik",
expected_fraktionen={"LINKE"},
datum="2026-04-08",
pdf_url_substring="dokument/",
frontend_search_url="https://www.buergerschaft-hh.de/parldok/",
),
# ─── TH (ParlDok 8.x) ───────────────────────────────────────────────
# 8/1594 vom 31.03.2026 hatte zum Test-Zeitpunkt noch keinen
# freigegebenen PDF-Link (allowed=false). Seit dem TH-Adapter-Patch
# in #61 werden solche Hits aus der Pipeline ausgeschlossen, der
# Sample muss daher auf einen leicht älteren Antrag mit
# garantiertem PDF zeigen.
GroundTruth(
bundesland="TH",
drucksache="8/3133",
title_substring="Notfallversorgung",
expected_fraktionen={"AfD"},
datum="2026-03-18",
pdf_url_substring="dokument/",
frontend_search_url="https://parldok.thueringer-landtag.de/parldok/",
),
# ─── SH (Starfinder-CGI) ────────────────────────────────────────────
GroundTruth(
bundesland="SH",
drucksache="20/4309",
title_substring="Gesunde Ernährung",
expected_fraktionen={"SSW"},
datum="2026-04-07",
pdf_url_substring="drucksache-20-04309",
frontend_search_url="http://lissh.lvn.parlanet.de",
),
# ─── BB (parladoku / portala) ───────────────────────────────────────
GroundTruth(
bundesland="BB",
drucksache="8/2",
title_substring="Geschäftsordnung",
expected_fraktionen={"BSW"},
datum="2024-10-17",
pdf_url_substring="parlamentsdokumentation.brandenburg.de",
frontend_search_url="https://www.parlamentsdokumentation.brandenburg.de/portal/",
),
# ─── RP (OPAL / portala) ────────────────────────────────────────────
# PDFs werden vom Landtag von `dokumente.landtag.rlp.de` ausgeliefert,
# nicht von `opal.rlp.de` (das ist nur das Suchfrontend). Substring auf
# die Drucksache-Nummer im Pfad — robust gegen weitere URL-Drift.
GroundTruth(
bundesland="RP",
drucksache="18/11250",
title_substring="Bildungschancen",
expected_fraktionen={"GRÜNE", "SPD", "FDP"},
datum="2025-01-23",
pdf_url_substring="11250-18",
frontend_search_url="https://opal.rlp.de/portal/",
),
]