aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/eu/mulk/aendggner/bericht/KorpusberichtTest.java134
-rw-r--r--src/test/resources/sampledata/korpus-grundlinie.tsv44
-rw-r--r--src/test/resources/sampledata/korpus.tsv46
3 files changed, 224 insertions, 0 deletions
diff --git a/src/test/java/eu/mulk/aendggner/bericht/KorpusberichtTest.java b/src/test/java/eu/mulk/aendggner/bericht/KorpusberichtTest.java
new file mode 100644
index 0000000..e709337
--- /dev/null
+++ b/src/test/java/eu/mulk/aendggner/bericht/KorpusberichtTest.java
@@ -0,0 +1,134 @@
+// SPDX-FileCopyrightText: 2026 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
+// SPDX-License-Identifier: AGPL-3.0-or-later
+package eu.mulk.aendggner.bericht;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Der Massenlauf über den Beispielkorpus, gehalten gegen die eingecheckte Grundlinie.
+ *
+ * <p>Die Einzelprüfungen sagen, dass ein bestimmtes Heft aufgeht. Diese sagt, dass keines der
+ * einunddreißig Hefte hinter das zurückfällt, was es einmal hergegeben hat — und zwar in einer
+ * Zahl, die sich fortschreiben lässt, statt in Dutzenden verstreuter Behauptungen.
+ */
+class KorpusberichtTest {
+
+ private static final Path SAMPLEDATA = Path.of("src/test/resources/sampledata");
+ private static final Path LISTE = SAMPLEDATA.resolve("korpus.tsv");
+ private static final Path GRUNDLINIE = SAMPLEDATA.resolve("korpus-grundlinie.tsv");
+
+ @Test
+ void derKorpusFaelltNichtHinterDieGrundlinieZurueck() throws Exception {
+ assumeTrue(Files.exists(LISTE) && Files.exists(GRUNDLINIE), "Korpusliste fehlt");
+ var auftraege = Korpusbericht.liesListe(LISTE);
+ assumeTrue(
+ auftraege.stream().allMatch(a -> Files.exists(SAMPLEDATA.resolve(a.stamm()))),
+ "Beispieldaten des Korpus fehlen");
+
+ var zeilen = Korpusbericht.fuehreAus(auftraege, SAMPLEDATA.toAbsolutePath(), null);
+
+ // Ein gescheiterter Auftrag hält den Lauf nicht an — unbemerkt bleiben darf er aber nicht;
+ // sonst meldete der Bericht lauter Nullen und niemand sähe den Grund.
+ assertThat(zeilen).hasSameSizeAs(auftraege);
+ assertThat(zeilen).allSatisfy(z -> assertThat(z.fehler()).isNull());
+
+ var ruegen =
+ Korpusbericht.gegenGrundlinie(zeilen, Files.readString(GRUNDLINIE, StandardCharsets.UTF_8));
+
+ assertThat(ruegen)
+ .as(
+ "Rückschritte gegenüber der Grundlinie; steht dagegen ein Fortschritt darin, so ist"
+ + " korpus-grundlinie.tsv fortzuschreiben:\n%s\n\nLauf:\n%s",
+ String.join("\n", ruegen), Korpusbericht.alsTsv(zeilen))
+ .isEmpty();
+ }
+
+ @Test
+ void dieListeWirdVollstaendigGelesen() throws Exception {
+ assumeTrue(Files.exists(LISTE), "Korpusliste fehlt");
+ var auftraege = Korpusbericht.liesListe(LISTE);
+
+ assertThat(auftraege).isNotEmpty();
+ // Kommentar- und Leerzeilen sind übergangen, „-“ heißt „nicht angegeben“.
+ assertThat(auftraege).noneMatch(a -> a.bezeichnung().startsWith("#"));
+ assertThat(auftraege).allSatisfy(a -> assertThat(a.hefte()).isNotEmpty());
+ var mitArtikel =
+ auftraege.stream().filter(a -> "GEG-BGBl-zeitrichtig".equals(a.bezeichnung())).findFirst();
+ assertThat(mitArtikel).isPresent();
+ assertThat(mitArtikel.orElseThrow().artikel()).isEqualTo("1");
+ assertThat(mitArtikel.orElseThrow().nachfassung()).isNull();
+ var mehrereHefte =
+ auftraege.stream()
+ .filter(a -> "BayJG-mit-Aenderungsantrag".equals(a.bezeichnung()))
+ .findFirst()
+ .orElseThrow();
+ assertThat(mehrereHefte.hefte()).hasSize(2);
+ var mitStichtag =
+ auftraege.stream()
+ .filter(a -> "IfSG-Stichtag".equals(a.bezeichnung()))
+ .findFirst()
+ .orElseThrow();
+ assertThat(mitStichtag.stichtag()).isNotNull();
+ }
+
+ @Test
+ void nurDerRueckschrittWirdGeruegt() {
+ var grundlinie =
+ """
+ # Bezeichnung\tBefehle\tangewandt\tmanuell\tzurückgestellt\tgleich\tgeprüft\tfehlend\tüberzählig\tabweichend\tGründe
+ Fall\t10\t8\t2\t0\t20\t22\t1\t0\t1\t-
+ """;
+
+ var besser =
+ List.of(new Korpusbericht.Zeile("Fall", 10, 9, 1, 0, 21, 22, 0, 0, 1, Map.of(), null));
+ assertThat(Korpusbericht.gegenGrundlinie(besser, grundlinie)).isEmpty();
+
+ var schlechter =
+ List.of(new Korpusbericht.Zeile("Fall", 10, 7, 3, 0, 19, 22, 1, 0, 2, Map.of(), null));
+ assertThat(Korpusbericht.gegenGrundlinie(schlechter, grundlinie))
+ .anySatisfy(r -> assertThat(r).contains("angewandte Befehle 7 statt 8"))
+ .anySatisfy(r -> assertThat(r).contains("liegengebliebene Befehle 3 statt 2"))
+ .anySatisfy(r -> assertThat(r).contains("gleiche Normen 19 statt 20"))
+ .anySatisfy(r -> assertThat(r).contains("abweichende Normen 2 statt 1"));
+ }
+
+ @Test
+ void einGescheiterterAuftragWirdGeruegtStattUebergangen() {
+ var grundlinie =
+ """
+ # Bezeichnung\tBefehle\tangewandt\tmanuell\tzurückgestellt\tgleich\tgeprüft\tfehlend\tüberzählig\tabweichend\tGründe
+ Fall\t10\t8\t2\t0\t-\t-\t-\t-\t-\t-
+ """;
+
+ var gescheitert =
+ List.of(
+ new Korpusbericht.Zeile(
+ "Fall", 0, 0, 0, 0, null, null, null, null, null, Map.of(), "IOException: weg"));
+ assertThat(Korpusbericht.gegenGrundlinie(gescheitert, grundlinie))
+ .singleElement()
+ .asString()
+ .contains("gescheitert");
+ }
+
+ @Test
+ void einVerschwundenerAuftragFaelltAuf() {
+ var grundlinie =
+ """
+ # Bezeichnung\tBefehle\tangewandt\tmanuell\tzurückgestellt\tgleich\tgeprüft\tfehlend\tüberzählig\tabweichend\tGründe
+ Fall\t10\t8\t2\t0\t-\t-\t-\t-\t-\t-
+ """;
+
+ assertThat(Korpusbericht.gegenGrundlinie(List.of(), grundlinie))
+ .singleElement()
+ .asString()
+ .contains("ist im Lauf aber nicht vorgekommen");
+ }
+}
diff --git a/src/test/resources/sampledata/korpus-grundlinie.tsv b/src/test/resources/sampledata/korpus-grundlinie.tsv
new file mode 100644
index 0000000..60da4f6
--- /dev/null
+++ b/src/test/resources/sampledata/korpus-grundlinie.tsv
@@ -0,0 +1,44 @@
+# Grundlinie des Korpuslaufs (§ 6d des Handbuchs), Stand 28. August 2026.
+#
+# Jede Zeile hält fest, was ein Auftrag der Liste „korpus.tsv“ zu diesem Zeitpunkt hergegeben hat.
+# Der Lauf wird dagegen gehalten (KorpusberichtTest, „--grundlinie“): Gerügt wird allein, was
+# FÄLLT — weniger erschlossene oder angewandte Befehle, weniger gleiche Normen, mehr
+# liegengebliebene, fehlende, überzählige oder abweichende. Ein Fortschritt ist kein Fehler,
+# sondern der Zweck der Arbeit; er verlangt allein, diese Datei fortzuschreiben.
+#
+# Die hohen Reste bei GEG-Beschlussempfehlung, IfSG-Beschlussempfehlung und RP-UKAPOGS beruhen
+# darauf, dass die Vorlage eine ältere Fassung fortschreibt als die eingesetzte Stammfassung
+# („Zieltext nicht vorhanden“); sie sind kein Mangel des Erzeugnisses, wohl aber ein Wächter:
+# Steigen sie, hat sich etwas verschlechtert.
+# Bezeichnung Befehle angewandt manuell zurückgestellt gleich geprüft fehlend überzählig abweichend Gründe
+UWG-BGBl 19 19 0 0 - - - - - -
+UWG-RegE 20 20 0 0 - - - - - -
+AGG-RegE 24 23 1 0 - - - - - Stelle nicht auffindbar:1
+ProdHaftG-RegE 1 1 0 0 - - - - - -
+GEG-BGBl-zeitrichtig 119 119 0 0 - - - - - -
+IfSG-BGBl-zeitrichtig 75 75 0 0 - - - - - -
+BayJG-GVBl 154 154 0 0 - - - - - -
+SN-SaechsBeamtVG 5 5 0 0 - - - - - -
+NI-NEFG 7 7 0 0 - - - - - -
+SH-Gemeindeordnung 1 1 0 0 167 167 0 0 0 -
+SH-Kreisordnung 1 1 0 0 86 86 0 0 0 -
+NRW-WDR-Gesetz 101 101 0 0 - - - - - -
+NRW-LMG 18 18 0 0 - - - - - -
+NRW-TMZ-Gesetz 4 4 0 0 - - - - - -
+NRW-17-RAEStV-AusfG 1 1 0 0 - - - - - -
+BE-ASOG 6 6 0 0 171 171 0 0 0 -
+BE-LAF-ErrG 2 2 0 0 5 5 0 0 0 -
+BW-KomWO 37 31 6 0 91 93 0 0 2 Befehl nicht erkannt:6
+HE-StVRZustV 21 21 0 0 52 52 0 0 0 -
+TH-KiGaFinVO 10 10 0 0 - - - - - -
+BB-FraktG 4 4 0 0 24 24 0 0 0 -
+HH-GutachterausschussVO 21 17 4 0 10 14 0 0 4 Befehl nicht erkannt:2; Stelle nicht auffindbar:1; Zieltext nicht vorhanden:1
+HB-BerufsfachschulVO 41 37 4 0 26 29 1 0 2 Befehl nicht erkannt:3; Fundstelle mehrdeutig:1
+MV-APOAmtsTA 24 20 4 0 - - - - - Befehl nicht erkannt:4
+RP-UKAPOGS 23 9 14 0 - - - - - Stelle nicht auffindbar:2; Zieltext nicht vorhanden:10; Bestand widerspricht dem Befehl:2
+GEG-GModG-RegE 97 87 10 0 - - - - - Befehl nicht erkannt:6; Stelle nicht auffindbar:2; Zieltext nicht vorhanden:2
+GEG-Beschlussempfehlung 119 70 49 0 - - - - - Befehl nicht erkannt:1; Stelle nicht auffindbar:3; Zieltext nicht vorhanden:40; Fundstelle mehrdeutig:1; Bestand widerspricht dem Befehl:4
+IfSG-Beschlussempfehlung 75 51 24 0 - - - - - Befehl nicht erkannt:1; Stelle nicht auffindbar:1; Zieltext nicht vorhanden:21; Bestand widerspricht dem Befehl:1
+BayJG-Landtagsentwurf 154 154 0 0 - - - - - -
+BayJG-mit-Aenderungsantrag 154 154 0 0 - - - - - -
+IfSG-Stichtag 75 65 0 10 - - - - - -
diff --git a/src/test/resources/sampledata/korpus.tsv b/src/test/resources/sampledata/korpus.tsv
new file mode 100644
index 0000000..2832539
--- /dev/null
+++ b/src/test/resources/sampledata/korpus.tsv
@@ -0,0 +1,46 @@
+# Auftragsliste des Korpuslaufs (§ 6d des Handbuchs).
+#
+# Spalten, durch Tabulator getrennt:
+# Bezeichnung | Stammfassung | Hefte (durch Komma) | Artikel | Nachfassung | Stichtag
+# „-“ heißt: nicht angegeben. Die Pfade beziehen sich auf das Verzeichnis dieser Datei.
+#
+# Aufgenommen ist, was die Akzeptanzprüfungen des EndToEndTest fahren. Deren Zahlen müssen hier
+# unverändert herauskommen; weichen sie ab, liegt der Fehler an der Liste und nicht am Erzeugnis.
+#
+# Bezeichnung Stamm Hefte Artikel Nachfassung Stichtag
+UWG-BGBl UWG/BJNR141400004.xml UWG/bgbl126s0043_regelungstext.pdf - - -
+UWG-RegE UWG/BJNR141400004.xml UWG/BT-Drs-21-1855_Regierungsentwurf.pdf - - -
+AGG-RegE AGG/BJNR189710006.xml AGG/BT-Drs-21-6178_Regierungsentwurf.pdf - - -
+ProdHaftG-RegE ProdHaftG/BJNR021980989.xml ProdHaftG/RegE_Produkthaftungsrecht_2025-12-17.pdf - - -
+GEG-BGBl-zeitrichtig GEG/BJNR172810020-2023.xml GEG/bgbl123s0280_regelungstext.pdf 1 - -
+IfSG-BGBl-zeitrichtig IfSG/BJNR104510000-2020.xml IfSG/bgbl120s2397_78991.pdf - - -
+BayJG-GVBl BayJG/BayJG-alt.txt BayJG/gvbl-2026-06.pdf - - -
+SN-SaechsBeamtVG Sachsen/SaechsBeamtVG-alt.txt Sachsen/SaechsGVBl-2026-S134_AendG-SaechsBeamtVG_revosax.pdf - - -
+NI-NEFG Niedersachsen/NEFG-alt.txt Niedersachsen/Nds-GVBl-2026-10_ELER-Foerdergesetz-AendG.pdf - - -
+SH-Gemeindeordnung SchleswigHolstein/GO-SH-alt.txt SchleswigHolstein/GVOBl-2026-27_Kommunalrecht-AendG.pdf 1 SchleswigHolstein/GO-SH-neu.txt -
+SH-Kreisordnung SchleswigHolstein/KrO-SH-alt.txt SchleswigHolstein/GVOBl-2026-27_Kommunalrecht-AendG.pdf 2 SchleswigHolstein/KrO-SH-neu.txt -
+NRW-WDR-Gesetz NRW/WDR-Gesetz-alt.txt NRW/GV-NRW-2026-S202_22-Rundfunkaenderungsgesetz.pdf - - -
+NRW-LMG NRW/LMG-NRW-alt.txt NRW/GV-NRW-2026-S202_22-Rundfunkaenderungsgesetz.pdf - - -
+NRW-TMZ-Gesetz NRW/TMZ-Gesetz-alt.txt NRW/GV-NRW-2026-S202_22-Rundfunkaenderungsgesetz.pdf - - -
+NRW-17-RAEStV-AusfG NRW/17-RAEStV-AusfG-alt.txt NRW/GV-NRW-2026-S202_22-Rundfunkaenderungsgesetz.pdf - - -
+BE-ASOG Berlin/ASOG-Bln-alt.txt Berlin/GVBl-2026-17_ASOG-LAF-AendG.pdf 1 Berlin/ASOG-Bln-neu.txt -
+BE-LAF-ErrG Berlin/LAF-ErrG-alt.txt Berlin/GVBl-2026-17_ASOG-LAF-AendG.pdf 2 Berlin/LAF-ErrG-neu.txt -
+BW-KomWO BadenWuerttemberg/KomWO-BW-alt.txt BadenWuerttemberg/GBl-2026-26_KommunalwahlO-AendVO.pdf - BadenWuerttemberg/KomWO-BW-neu.txt -
+HE-StVRZustV Hessen/StVRZustV-alt.txt Hessen/GVBl-2026-05_11-AendVO-verkehrsrechtl-Zustaendigkeiten.pdf - Hessen/StVRZustV-neu.txt -
+TH-KiGaFinVO Thueringen/ThuerKigaFinVO-alt.txt Thueringen/GVBl-TH-2026-02_KiGaFinanzVO-AendVO-ua.pdf - - -
+BB-FraktG Brandenburg/FraktG-alt.txt Brandenburg/GVBl-I-2026-12_FraktG-AendG.pdf - Brandenburg/FraktG-neu.txt -
+HH-GutachterausschussVO Hamburg/GAusschV-HH-alt.txt Hamburg/HmbGVBl-2026-17_GutachterausschussVO-AendVO.pdf - Hamburg/GAusschV-HH-neu.txt -
+HB-BerufsfachschulVO Bremen/AssBerFSchulV-BR-alt.txt Bremen/BremGBl-2026-87_BerufsfachschulVO-AendVO.pdf - Bremen/AssBerFSchulV-BR-neu.txt -
+MV-APOAmtsTA MecklenburgVorpommern/APOAmtsTA-MV-alt.txt MecklenburgVorpommern/GVOBl-MV-2026-21_Besoldungsanpassung-ua.pdf 44 - -
+# Rheinland-Pfalz führt keine Vorfassungen; angewandt wird deshalb auf die Nachfassung, und
+# aussagekräftig ist allein die Zahl der erschlossenen Befehle (23). Die liegengebliebenen sind
+# die Folge des falschen Standes, nicht eines Mangels — siehe § 13 Absatz 4 des Handbuchs.
+RP-UKAPOGS RheinlandPfalz/UKAPOGS-E3-neu.txt RheinlandPfalz/GVBl-2026-21_UKAPOGS-E3-AendVO.pdf - - -
+# Entwürfe und Zusammenstellungen: hier gibt es keine Nachfassung, wohl aber die Frage, wie viel
+# eine Vorlage hergibt.
+GEG-GModG-RegE GEG/BJNR172810020.xml GEG/Regierungsentwurf_GModG_2026-05-13.pdf - - -
+GEG-Beschlussempfehlung GEG/BJNR172810020.xml GEG/BT-Drs-20-7619_Beschlussempfehlung.pdf - - -
+IfSG-Beschlussempfehlung IfSG/BJNR104510000.xml IfSG/1924334.pdf - - -
+BayJG-Landtagsentwurf BayJG/BayJG-alt.txt BayJG/Ltg-Drs-19-9707_Gesetzentwurf.pdf - - -
+BayJG-mit-Aenderungsantrag BayJG/BayJG-alt.txt BayJG/Ltg-Drs-19-9707_Gesetzentwurf.pdf,BayJG/Ltg-Drs-19-10365_Aenderungsantrag-Gruene.pdf - - -
+IfSG-Stichtag IfSG/BJNR104510000-2020.xml IfSG/bgbl120s2397_78991.pdf - - 2020-11-19