155 lines
5.5 KiB
Markdown
155 lines
5.5 KiB
Markdown
---
|
||
model: sonnet
|
||
---
|
||
# AP10 – Architekturtest
|
||
|
||
> **Meilenstein:** M1
|
||
> **Vorgänger:** AP04, AP09 ✅ erforderlich (alle AP05–AP09 sollten abgeschlossen sein)
|
||
> **Nachfolger:** AP11
|
||
> **Grundlage:** `docs/specs/technik-und-architektur.md` v5, §§ „Architekturprinzipien", „Test- und Qualitätsanforderungen"
|
||
> **Entscheidungsprotokoll:** `docs/arbeitspakete/m1/E00-entscheidungsprotokoll.md` (E-02 Test-Log, E-03 leere Testklasse)
|
||
|
||
## Ziel
|
||
|
||
Automatisierte Architekturtests sichern die in M1 etablierten Strukturregeln dauerhaft ab. Zusätzlich wird das Build-Rauschen durch ERROR-Log-Zeilen in Negativ-Tests beseitigt.
|
||
|
||
## Voraussetzungen
|
||
|
||
- AP04 (Logging-Adapter etabliert)
|
||
- AP09 (Preview-Code eingefroren)
|
||
- Idealerweise alle AP05–AP09 abgeschlossen
|
||
|
||
## Scope IN
|
||
|
||
### 1. ArchUnit als Test-Dependency
|
||
|
||
```xml
|
||
<dependency>
|
||
<groupId>com.tngtech.archunit</groupId>
|
||
<artifactId>archunit-junit5</artifactId>
|
||
<version><!-- aktuell stabile Version --></version>
|
||
<scope>test</scope>
|
||
</dependency>
|
||
```
|
||
|
||
### 2. Architekturtest-Klasse
|
||
|
||
Neue Testklasse `de.gecheckt.asv.ArchitectureTest` im Testbereich. Mindestens vier Regeln:
|
||
|
||
**Regel A — Log4j2-Sichtbarkeit:**
|
||
```java
|
||
@ArchTest
|
||
static final ArchRule log4j2_nur_in_logging_adapter_und_bootstrap =
|
||
noClasses()
|
||
.that().resideOutsideOfPackages(
|
||
"de.gecheckt.asv.adapter.out.logging..",
|
||
"de.gecheckt.asv.bootstrap..")
|
||
.should().dependOnClassesThat()
|
||
.resideInAPackage("org.apache.logging.log4j..")
|
||
.because("Log4j2 darf nur im Logging-Adapter und im Bootstrap sichtbar sein.");
|
||
```
|
||
|
||
**Regel B — Domain-Reinheit:**
|
||
```java
|
||
@ArchTest
|
||
static final ArchRule domain_hat_keine_adapter_abhaengigkeit =
|
||
noClasses()
|
||
.that().resideInAPackage("de.gecheckt.asv.domain..")
|
||
.should().dependOnClassesThat()
|
||
.resideInAnyPackage(
|
||
"de.gecheckt.asv.adapter..",
|
||
"de.gecheckt.asv.bootstrap..");
|
||
```
|
||
|
||
**Regel C — Application-Reinheit:**
|
||
```java
|
||
@ArchTest
|
||
static final ArchRule application_kennt_keine_adapter_implementierungen =
|
||
noClasses()
|
||
.that().resideInAPackage("de.gecheckt.asv.application..")
|
||
.should().dependOnClassesThat()
|
||
.resideInAnyPackage(
|
||
"de.gecheckt.asv.adapter..",
|
||
"de.gecheckt.asv.bootstrap..");
|
||
```
|
||
|
||
**Regel D — Preview-Isolation:**
|
||
```java
|
||
@ArchTest
|
||
static final ArchRule preview_wird_nicht_aus_aktivem_code_referenziert =
|
||
noClasses()
|
||
.that().resideInAnyPackage(
|
||
"de.gecheckt.asv.adapter..",
|
||
"de.gecheckt.asv.bootstrap..")
|
||
.should().dependOnClassesThat()
|
||
.haveSimpleNameContaining("DefaultStructureValidator")
|
||
.orShould().dependOnClassesThat()
|
||
.haveSimpleNameContaining("DefaultFieldValidator")
|
||
.because("Preview-Validatoren sind in M1 eingefroren und werden erst ab M3 aktiv verwendet.");
|
||
```
|
||
|
||
**Wichtig:** Wenn beim ersten Lauf Regeln rot sind, **müssen die Verstöße behoben werden** — die Regeln werden nicht abgeschwächt.
|
||
|
||
### 3. Test-Log-Konfiguration (E-02)
|
||
|
||
`src/test/resources/log4j2-test.xml` anlegen:
|
||
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<Configuration status="WARN">
|
||
<Appenders>
|
||
<Console name="Console" target="SYSTEM_ERR">
|
||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
|
||
</Console>
|
||
</Appenders>
|
||
<Loggers>
|
||
<Root level="WARN">
|
||
<AppenderRef ref="Console"/>
|
||
</Root>
|
||
</Loggers>
|
||
</Configuration>
|
||
```
|
||
|
||
Log4j2 bevorzugt `log4j2-test.xml` im Test-Classpath gegenüber `log4j2.xml`. Das unterdrückt die erwartete ERROR-Zeile aus dem CLI-Negativ-Test.
|
||
|
||
### 4. Aufräumen
|
||
|
||
- Prüfen ob `DefaultStructureValidatorTestAdditional` bereits in AP09 gelöscht wurde — falls nicht, hier löschen
|
||
- Sicherstellen dass keine weiteren leeren Testklassen im Projekt existieren
|
||
|
||
## Scope OUT
|
||
|
||
- Komplexe Regeln wie zyklische Abhängigkeiten — für M1 zu weitgehend
|
||
- Regeln zu Klassenbenennung oder `public`-Sichtbarkeit
|
||
- Coverage- und Mutation-Schwellwerte (kommen erst in M9)
|
||
- Neue Produktionsklassen
|
||
|
||
## Schritte
|
||
|
||
1. ArchUnit in `pom.xml` als Test-Dependency aufnehmen
|
||
2. `ArchitectureTest`-Klasse mit den vier Regeln implementieren
|
||
3. `log4j2-test.xml` unter `src/test/resources/` anlegen
|
||
4. `mvn clean verify` ausführen — alle vier ArchUnit-Regeln müssen grün sein
|
||
5. Falls Regeln rot: Verstöße identifizieren, beheben, erneut testen
|
||
6. Im Bericht dokumentieren ob beim ersten Lauf Regeln rot waren und wie behoben
|
||
7. Abschlussbericht schreiben
|
||
|
||
## Abnahmekriterien
|
||
|
||
- [ ] ArchUnit als Test-Dependency in `pom.xml`
|
||
- [ ] Vier Architekturregeln A–D implementiert und grün
|
||
- [ ] `log4j2-test.xml` unter `src/test/resources/` vorhanden
|
||
- [ ] Keine leeren Testklassen im Projekt
|
||
- [ ] `mvn clean verify` grün, kein unerwartetes Log-Rauschen
|
||
- [ ] Bericht dokumentiert ob erste Ausführung Regeln rot hatte und wie behoben
|
||
- [ ] Abschlussbericht unter `docs/arbeitspakete/m1/berichte/AP10-bericht.md`
|
||
|
||
## Rest-Risiken und offene Punkte
|
||
|
||
- ArchUnit hat beim ersten Einsatz manchmal Überraschungen mit transitiven Abhängigkeiten (Regel greift auch auf Framework-Klassen). In dem Fall: Regel präzisieren, **nicht** ausschalten.
|
||
- Regel D (Preview-Isolation) ist auf Klassennamen-Basis formuliert, weil kein separates Paket existiert (Option b). Falls das zu fragil ist, kann alternativ auf Package-Ebene mit einem `preview`-Paket geprüft werden — aber nur wenn AP09 entsprechend umgebaut wurde.
|
||
|
||
## Bericht
|
||
|
||
`docs/arbeitspakete/m1/berichte/AP10-bericht.md` nach `docs/arbeitspakete/m1/templates/ap-bericht.md`.
|