diff options
| author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-28 08:13:29 +0200 |
|---|---|---|
| committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-28 08:13:29 +0200 |
| commit | 0be6e41ca5ae1c16aab308931616f1ec84ea3eba (patch) | |
| tree | d2d5342f687747b36c0ad00798df34c62ea73a95 /src/test/java | |
| parent | 3203725daa2c8db9ce25ff4541dd4ea438ac5cd7 (diff) | |
Der Korpus sagt, woran die Reste im Ganzen liegen
Der Befund über das Erzeugnis ruhte auf handverlesenen Fällen. Rund drei Dutzend
Akzeptanzprüfungen sagen, dass diese Hefte aufgehen; sie sagen nicht, woran die
Reste im Ganzen liegen — ob an der Befehlssprache eines Landes, an der
Aufbereitung des Druckwerks oder am Alter der eingesetzten Stammfassung. Die
Auszählung der Gründe beantwortet das für ein Heft; über einen Korpus geführt
beantwortet sie es für das Erzeugnis.
Der Schalter --korpus arbeitet eine Auftragsliste ab und gibt je Auftrag eine
Zeile Kennzahlen aus: erschlossene, angewandte, liegengebliebene und am Stichtag
zurückgestellte Befehle, sodann die gleichen, geprüften, fehlenden, überzähligen
und abweichenden Normen des Abgleichs, zuletzt die Gründe nach Häufigkeit. Die
Liste nennt dieselben Angaben, die auch die Befehlszeile entgegennimmt — ein
Auftrag ist nichts anderes als ein Lauf. Mit --synopsen bleiben die
Einzelsynopsen samt einer Übersichtsseite stehen; ohne sie wäre der Bericht eine
Zahlenreihe, aus der niemand den Grund eines Restes erführe.
Eingecheckt ist der Bericht die Grundlinie. --grundlinie hält den Lauf dagegen
und rügt 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, die Grundlinie fortzuschreiben. Der Rückschritt endet mit 3 wie ein nicht
aufgehender Abgleich. Ein gescheiterter Auftrag hält den Lauf nicht an, sondern
trägt seinen Fehlertext in seiner Zeile — der Grundsatz der Nichtverwerfung gilt
auch hier.
Der mitgelieferte Korpus umfasst einunddreißig Aufträge und gibt 1413 Befehle
her, von denen 1287 angewandt werden; 632 von 641 verglichenen Normen gehen auf.
Er reproduziert die Zahlen der bestehenden Akzeptanzfälle (UWG 19/0, GEG 119/119,
BayJG 154/154, Berlin 171/171, WDR 101, Bremen 41/37, Hamburg 21/17). Drei
Aufträge tragen mit Absicht hohe Reste: Bei den beiden Beschlussempfehlungen und
bei Rheinland-Pfalz schreibt die Vorlage eine ältere Fassung fort als die
eingesetzte Stammfassung. Sie sind gleichwohl Wächter — steigen ihre Reste, so
hat sich etwas verschlechtert.
Nebenbei: Die Auszählung der Gründe stand doppelt (Befehlszeile und Synopse) und
liegt nun in Pipeline.zaehleGruende; das Ergebnis der Pipeline führt sie mit.
Geprüft: mvnw verify (443 Testfälle) und reuse lint (214/214) gehen durch; der
Korpuslauf ist Teil der Prüfung. Die Rügeregel ist am ganzen Korpus erprobt: Eine
um eins verschärfte Grundlinie führt zur Rüge „UWG-BGBl: angewandte Befehle 19
statt 20“ und zum Rückgabewert 3.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I4e10b041b78d95772da1c3ff18ab92b0b45dacaa
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/bericht/KorpusberichtTest.java | 134 |
1 files changed, 134 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"); + } +} |
