M1-AP02: Build-Infrastruktur härten (SLF4J, JaCoCo, PIT, JAR-Plugin,

Mockito-Agent)
This commit is contained in:
2026-04-09 07:12:14 +02:00
parent 61935df80f
commit d0aac6a9ac
4 changed files with 295 additions and 12 deletions

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
# EditorConfig — https://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
[*.java]
indent_style = space
indent_size = 4
[*.xml]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false

5
.gitattributes vendored Normal file
View File

@@ -0,0 +1,5 @@
# Git-Attribute — Zeilenenden normalisieren
* text=auto eol=lf
*.bat text eol=crlf
*.java text eol=lf
*.md text eol=lf

View File

@@ -0,0 +1,138 @@
# Abschlussbericht AP02 Build-Infrastruktur härten
> **Bezug:** `docs/arbeitspakete/m1/AP02-build-infrastruktur.md`
> **Bearbeiter:** Claude Code (claude-sonnet-4-6)
> **Datum:** 2026-04-09
> **Commit(s):** — (kein Commit in AP02; der Mensch committet nach Prüfung)
> **Status:** ✅ abgeschlossen
---
## 1. Zusammenfassung
AP02 hat die Build-Infrastruktur vollständig gehärtet: SLF4J als Logging-Fassade (Compile) und `log4j-slf4j2-impl` als Runtime-Bindung wurden hinzugefügt, JaCoCo und PIT (im Profil `mutation`) konfiguriert, das `maven-jar-plugin` mit Platzhalter-`Main-Class` eingerichtet, und Mockito als expliziter Java-Agent in `maven-surefire-plugin` eingehängt. Die Mockito-ByteBuddy-Warnung aus AP01 ist verschwunden. Beide Build-Ziele (`mvn clean verify` und `mvn -P mutation test`) sind grün.
---
## 2. Umgesetzte Änderungen
- `pom.xml` — neue Properties: `slf4j.version=2.0.7`, `jacoco-maven-plugin.version=0.8.10`, `maven-dependency-plugin.version=3.6.0`, `maven-jar-plugin.version=3.3.0`
- `pom.xml` — neue Dependency: `org.slf4j:slf4j-api:2.0.7` (Scope: compile; Logging-Fassade)
- `pom.xml` — neue Dependency: `org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0` (Scope: runtime; SLF4J→Log4j2-Bridge)
- `pom.xml` — neues Plugin: `maven-dependency-plugin:3.6.0` mit Goal `properties` (liefert Jar-Pfade für Java-Agent)
- `pom.xml``maven-surefire-plugin` erweitert: `argLine` mit `@{argLine} -javaagent:${org.mockito:mockito-core:jar}` (Mockito als expliziter Java-Agent; JaCoCo-argLine per Late-Binding)
- `pom.xml` — neues Plugin: `maven-jar-plugin:3.3.0` mit `mainClass=de.gecheckt.asv.bootstrap.Main`
- `pom.xml` — neues Plugin: `jacoco-maven-plugin:0.8.10` mit Goals `prepare-agent` und `report` (an `verify` gebunden; keine Schwellwerte)
- `pom.xml` — neues Profil `mutation` mit `pitest-maven:1.15.3` + `pitest-junit5-plugin:1.2.1` (JUnit-5-Adapter), Goal `mutationCoverage` in Phase `test`
- `.editorconfig` — neu angelegt (UTF-8, LF, 4 Spaces für Java/XML, trim + final newline)
- `.gitattributes` — neu angelegt (`* text=auto eol=lf`, `*.bat eol=crlf`, `*.java eol=lf`, `*.md eol=lf`)
---
## 3. Scope-Treue
| Scope-Punkt aus dem Arbeitspaket | Erfüllt? | Bemerkung |
|---|---|---|
| `slf4j-api` als Compile-Dependency | ✅ | Version 2.0.7 (kompatibel mit Log4j2 2.20.0 / `log4j-slf4j2-impl`) |
| `log4j-slf4j2-impl` als Runtime-Bindung | ✅ | Scope runtime |
| `maven-jar-plugin` mit `Main-Class` | ✅ | Platzhalter `de.gecheckt.asv.bootstrap.Main` (wird in AP06 real) |
| `jacoco-maven-plugin` an `verify` gebunden, ohne Schwellwerte | ✅ | prepare-agent + report, kein check-Goal |
| `pitest-maven` im Profil `mutation`, ohne Schwellwerte | ✅ | Profil-Name exakt `mutation`; kein mutationThreshold |
| Mockito als Java-Agent via `maven-surefire-plugin` argLine | ✅ | Warnung aus AP01 beseitigt |
| `.editorconfig` anlegen | ✅ | Neue Datei im Repo-Root |
| `.gitattributes` anlegen | ✅ | Neue Datei im Repo-Root (existierte nicht) |
| Keine Änderungen an `.java`-Dateien | ✅ | Keine Java-Datei angefasst |
| Keine Coverage-Schwellwerte | ✅ | Kein `check`-Goal, keine `<rules>` |
| Keine PIT-Schwellwerte | ✅ | Kein `mutationThreshold`, kein `coverageThreshold` |
**Wurde der Scope eingehalten?** Ja, vollständig.
**Wurden Dinge außerhalb des Scopes gemacht?** Nein. Der einzige über den schriftlichen Scope hinausgehende Punkt ist die `pitest-junit5-plugin`-Dependency im PIT-Plugin, die technisch zwingend nötig ist, damit PIT JUnit-5-Tests überhaupt ausführen kann — ohne sie bricht `mvn -P mutation test` mit BUILD FAILURE ab. Das ist eine technische Voraussetzung des Abnahmekriteriums, nicht eine Scope-Erweiterung.
---
## 4. Abnahmekriterien
| Abnahmekriterium aus dem Arbeitspaket | Erfüllt? | Nachweis |
|---|---|---|
| `pom.xml` enthält `slf4j-api` | ✅ | `<artifactId>slf4j-api</artifactId>` in `<dependencies>` |
| `pom.xml` enthält `log4j-slf4j2-impl` | ✅ | `<artifactId>log4j-slf4j2-impl</artifactId>` in `<dependencies>` |
| `pom.xml` enthält `maven-jar-plugin` | ✅ | `maven-jar-plugin:3.3.0` mit `mainClass` |
| `pom.xml` enthält `jacoco-maven-plugin` | ✅ | `jacoco-maven-plugin:0.8.10`, zwei Executions |
| `pom.xml` enthält `pitest-maven` | ✅ | Im Profil `mutation`, `pitest-maven:1.15.3` |
| `mvn clean verify` ist grün | ✅ | BUILD SUCCESS, 147 Tests, 0 Failures, 0 Errors |
| `mvn -P mutation test` läuft ohne Fehler | ✅ | BUILD SUCCESS; 249 Mutationen, 207 getötet (83%), Laufzeit ~39 s |
| JaCoCo-Report unter `target/site/jacoco/` | ✅ | `target/site/jacoco/index.html` und Paket-Reports vorhanden |
| Mockito-Warnung „self-attaching via ByteBuddy" nicht mehr im Log | ✅ | Grep über Build-Log: kein Treffer für „self-attach", „ByteBuddy", „dynamic loading" |
| `.editorconfig` liegt im Repo-Root | ✅ | `D:\Dev\Projects\asv-format-validator\.editorconfig` |
| `.gitattributes` liegt im Repo-Root | ✅ | `D:\Dev\Projects\asv-format-validator\.gitattributes` |
| Keine Änderungen an `.java`-Dateien | ✅ | `git status` zeigt nur `pom.xml`, `.editorconfig`, `.gitattributes` |
---
## 5. Build- und Teststatus
### 5.1 `mvn clean verify`
- **Ergebnis:** ✅ BUILD SUCCESS
- **Anzahl Tests:** 147 (0 neu; AP02 ändert keinen Testcode)
- **Fehler / Skipped:** 0 / 0
- **Dauer:** ~22 s
- **JaCoCo:** Report erzeugt unter `target/site/jacoco/`
**Warnungen beim Build:**
| Warnung | Quelle | Bewertung |
|---|---|---|
| `Java HotSpot VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended` | HotSpot / JaCoCo-Agent | Unvermeidlich wenn JaCoCo-Agent den bootstrap classpath erweitert; kosmetisch, nicht blockierend. War bereits in AP01 vorhanden. |
| `[ERROR] ... Fehler beim Lesen der Datei: File does not exist: /non/existent/file.txt` | Log4j2-Testausgabe in `AsvValidatorApplicationTest` | Erwartete Test-Logausgabe, kein echter Fehler |
Die Mockito-Warnungen aus AP01 (`Mockito is currently self-attaching`, `WARNING: Dynamic loading of agents will be disallowed`) sind **nicht mehr vorhanden**.
### 5.2 `mvn -P mutation test`
- **Ergebnis:** ✅ BUILD SUCCESS
- **Generierte Mutationen:** 249
- **Getötet:** 207 (83%)
- **Test-Strength:** 92%
- **Line Coverage (mutierte Klassen):** 91%
- **Laufzeit PIT:** ~29 s (Gesamt-Build ~39 s)
- **Anmerkung:** Mutation-Score ist in M1 irrelevant; Schwellwerte kommen in M9.
---
## 6. Rest-Risiken und offene Punkte
1. **`pitest-junit5-plugin` nicht im AP-Dokument erwähnt:** Das AP-Dokument nennt `pitest-maven`, aber nicht die erforderliche JUnit-5-Adapter-Dependency. Ohne sie bricht PIT mit BUILD FAILURE ab. Der Adapter (`pitest-junit5-plugin:1.2.1`) wurde als Pflicht-Ergänzung hinzugefügt und ist im Profil `mutation` kapselt. Kein Risiko für M1; in M9 muss beim Versions-Update beachtet werden, dass PIT-Plugin und JUnit-5-Adapter zueinander kompatibel bleiben.
2. **`Main-Class`-Eintrag zeigt auf nicht-existente Klasse:** `de.gecheckt.asv.bootstrap.Main` existiert erst ab AP06. Das JAR ist bis dahin mit `java -jar` nicht startbar, was aber kein M1-Blockers ist. In AP06 wird die Klasse angelegt und der Eintrag damit valide.
3. **HotSpot-Sharing-Warnung bleibt:** Die Warnung `Sharing is only supported for boot loader classes` entsteht durch den JaCoCo-Agenten und ist unvermeidlich. Sie ist kosmetisch und nicht blockierend.
4. **SLF4J-API vorhanden, aber noch kein Code nutzt sie:** Erst ab AP04 werden die Log4j2-Direktimporte auf SLF4J umgestellt. Bis dahin liegt `slf4j-api` ungenutzt im Classpath — das ist der gewollte Zustand und erzeugt keine Fehler.
5. **`mvn -P mutation test` und Mockito-Agent:** PIT startet einen eigenen Minion-Prozess; der Mockito-Java-Agent in `argLine` von Surefire hat keinen Einfluss auf den PIT-Minion. Das ist unkritisch, da PIT keine Mockito-Interaktion benötigt.
---
## 7. Empfehlungen für Folge-Arbeitspakete
- **AP03 (Paketstruktur):** Keine Build-Infrastruktur-Abhängigkeiten. Kann direkt auf Basis der Klassifikationstabelle aus AP01 starten.
- **AP04 (Logging-Umstellung):** `slf4j-api` und `log4j-slf4j2-impl` sind bereit. AP04 darf jetzt die Log4j2-Direktimporte in `AsvValidatorApplication` auf SLF4J-Logger umstellen. Kein `pom.xml`-Anpassungsbedarf in AP04.
- **AP06 (Bootstrap/CLI):** `maven-jar-plugin` zeigt auf `de.gecheckt.asv.bootstrap.Main`. AP06 muss diese Klasse anlegen (oder den Eintrag auf die finale Klasse umbiegen) und den `argLine`-Kommentar in `pom.xml` aktualisieren, falls sich der Klassenname ändert.
- **M9 (Quality-Gates):** JaCoCo und PIT sind ohne Schwellwerte eingerichtet. In M9 werden Coverage- und Mutation-Schwellwerte als `<rules>` in `jacoco-maven-plugin` bzw. als `mutationThreshold`/`coverageThreshold` in `pitest-maven` ergänzt. Beim Update von `pitest-junit5-plugin` auf die dann aktuelle Version sicherstellen, dass Kompatibilität mit `pitest-maven` gewahrt bleibt.
---
## 8. Reviewer-Checkliste
- [x] Alle im Arbeitspaket genannten Scope-IN-Punkte sind nachweislich umgesetzt (Abschnitte 2 und 3)
- [x] Keine Scope-OUT-Punkte wurden angefasst (keine `.java`-Dateien, keine Coverage-Schwellwerte, keine PIT-Schwellwerte)
- [x] Abnahmekriterien sind mit konkreten Nachweisen belegt (Abschnitt 4)
- [x] `mvn clean verify` ist grün (147 Tests, BUILD SUCCESS — Abschnitt 5.1)
- [ ] Der Commit für dieses AP hat eine sprechende Message (`M1-AP02: Build-Infrastruktur härten`) — _Commit liegt beim Menschen_
- [x] Keine Regeln der Grunddokumente (Spec, Fachliche, Technik) wurden verletzt
- [x] Rest-Risiken sind ehrlich dokumentiert (Abschnitt 6)

121
pom.xml
View File

@@ -17,16 +17,35 @@
<!-- Dependency Versions --> <!-- Dependency Versions -->
<log4j.version>2.20.0</log4j.version> <log4j.version>2.20.0</log4j.version>
<slf4j.version>2.0.7</slf4j.version>
<junit.version>5.9.2</junit.version> <junit.version>5.9.2</junit.version>
<mockito.version>5.23.0</mockito.version> <mockito.version>5.23.0</mockito.version>
<!-- Plugin Versions --> <!-- Plugin Versions -->
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-dependency-plugin.version>3.6.0</maven-dependency-plugin.version>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
<maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version> <maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version>
<jacoco-maven-plugin.version>0.8.10</jacoco-maven-plugin.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- Log4j2 API --> <!-- SLF4J API (Logging-Fassade; Bindung an Log4j2 erfolgt zur Laufzeit) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Log4j2-SLF4J-Bridge (Runtime-Bindung: SLF4J → Log4j2) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Log4j2 API (bis AP04 direkt genutzt; danach nur noch indirekt via SLF4J) -->
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId> <artifactId>log4j-api</artifactId>
@@ -68,11 +87,111 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- Löst Jar-Pfade für Dependencies auf; liefert u.a. den Pfad
zum Mockito-Core-JAR für den expliziten Java-Agent in Surefire -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<id>get-mockito-agent-path</id>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- @{argLine} wird von JaCoCo prepare-agent (Late-Binding) befüllt.
Mockito wird als expliziter Java-Agent eingehängt, um die
ByteBuddy-Self-Attach-Warnung zu vermeiden (AP01, Rest-Risiko 2). -->
<argLine>@{argLine} -javaagent:${org.mockito:mockito-core:jar}</argLine>
</configuration>
</plugin>
<!-- Ausführbares JAR; Main-Class-Klasse wird in AP06 angelegt -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<manifest>
<mainClass>de.gecheckt.asv.bootstrap.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- JaCoCo: Coverage-Messung ohne Schwellwerte (Schwellen kommen in M9) -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<id>jacoco-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles>
<!-- Mutation-Tests via PIT; aktiviert mit: mvn -P mutation test
Schwellwerte werden erst in M9 gesetzt. -->
<profile>
<id>mutation</id>
<build>
<plugins>
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.15.3</version>
<dependencies>
<!-- JUnit 5 Adapter für PIT (ohne dieses Plugin kann PIT keine JUnit-5-Tests laufen lassen) -->
<dependency>
<groupId>org.pitest</groupId>
<artifactId>pitest-junit5-plugin</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
<configuration>
<targetClasses>
<param>de.gecheckt.asv.*</param>
</targetClasses>
<targetTests>
<param>de.gecheckt.asv.*</param>
</targetTests>
</configuration>
<executions>
<execution>
<id>pit-mutation</id>
<phase>test</phase>
<goals>
<goal>mutationCoverage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project> </project>