From 379d00542a267b7242bd2ef9934f38ea7a013418 Mon Sep 17 00:00:00 2001 From: Jens Date: Thu, 16 Jul 2026 12:16:59 +0200 Subject: [PATCH] docs: update testing strategy and define directory symmetry --- architektur-patterns.md | 42 +++++++++++++++++++++++++++++++++++++++-- architektur.md | 17 +++++++++-------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/architektur-patterns.md b/architektur-patterns.md index 9b13bbc..aa97453 100644 --- a/architektur-patterns.md +++ b/architektur-patterns.md @@ -634,8 +634,46 @@ readonly class ShippingProvider implements ShippingProviderInterface return $this->mapper->toModel($response); } catch (TransportException $e) { throw new ExternalSystemUnavailableException('Shipping API is down', 0, $e); - } - } + +## 13. Testing Strategy & Structure +Die Testsuite ist so aufgebaut, dass sie die Schichtenmodell-Architektur widerspiegelt. Dies erleichtert die Wartung und stellt sicher, dass jede Komponente auf der richtigen Abstraktionsebene geprüft wird. + +### Verzeichnisstruktur & Mapping +Die Struktur unter `tests/` folgt strikt der Symmetrie zu `src/`: + +| Test Typ | Pfad in `tests/` | Spiegelt $\rightarrow$ | Werkzeug / Ansatz | Fokus | +| :--- | :--- | :--- | :--- | :--- | +| **Unit** | `tests/Unit/Logic/` | `src/Logic/` | PHPUnit + Mocks | Pure Business Logic & Edge Cases. | +| **Integration** | `tests/Integration/Data/` | `src/Data/` | Real DB (Test-Env) | Repositories, Mapper, Infrastruktur. | +| **Functional UI**| `tests/Functional/UI/` | `src/UI/` | Symfony `WebTestCase` | Einzelspezifische Endpunkte / Requests. | +| **Functional E2E**| `tests/Functional/Scenarios/`| (Szenario-basiert) | Symfony `WebTestCase` | Komplexe User Flows (Multi-Step). | + +--- + +### Detaillierte Guidelines + +#### 1. Unit Tests (`tests/Unit/Logic`) +Da die Logic Layer "Pure PHP" ist, müssen diese Tests extrem schnell sein. +- **Kein Framework**: Es wird kein Symfony Kernel gebootet. +- **Mocking**: Interfaces der Data Layer (`Provider`, `Processor`, `TransactionManager`) werden gemockt. +- **Business Models**: Werden *nicht* gemockt, sondern echt verwendet (da sie zustandslos/POPOs sind). + +#### 2. Integration Tests (`tests/Integration/Data`) +Hier wird die Brücke zur Infrastruktur geprüft. +- **Datenbank**: Nutzung einer dedizierten Test-DB. Jeder Test sollte in einer Transaktion laufen, die am Ende gerolled wird (oder via Database-Reset). +- **Mapper-Tests**: Explizite Prüfung: `Entity` $\rightarrow$ `toModel()` $\rightarrow$ `Business Model`. + +#### 3. Functional Tests (`tests/Functional`) +Diese nutzen den Symfony `WebTestCase`, um das System als "Black Box" zu testen. +- **UI Mirroring**: In `tests/Functional/UI` wird pro Controller ein entsprechender Test-Case angelegt, der die HTTP-Antworten (Status-Codes, JSON-Struktur) validiert. +- **Scenario-Tests**: In `tests/Functional/Scenarios` werden reale Business Flows abgebildet (z.B. `OrderProcessTest`), die mehrere API-Calls hintereinander ausführen und den finalen Zustand in der Datenbank prüfen. + +#### 4. Mocking Guidelines +Um "fragile Tests" zu vermeiden, gilt: +- **Mock a Interface, not a Class**: Mocke immer das Interface (z.B. `OrderProviderInterface`), niemals die konkrete Implementierung (`OrderProvider`). +- **No Mocks for Models/DTOs**: Value Objects und Business Models werden immer echt instanziiert. +- **Avoid Mocking 3rd Party Libs**: Wenn externe Libs getestet werden müssen, schreibe einen eigenen Wrapper/Interface in die Logic Layer und mocke diesen. + } ``` diff --git a/architektur.md b/architektur.md index 7861d5e..2f7074e 100644 --- a/architektur.md +++ b/architektur.md @@ -72,21 +72,22 @@ Zur Entkopplung zeitintensiver Prozesse wird ein Message-Bus eingesetzt. Dabei g - **Ort**: Message-Handler befinden sich in der **UI Layer**. - **Rolle**: Da ein asynchroner Nachrichteneingang ein externer Eintrittspunkt ist, fungiert der Handler als Adapter. Er nimmt die Message entgegen und delegiert die eigentliche Verarbeitung an einen entsprechenden UseCase oder Workflow in der Logic Layer. -## 6. Teststrategie - -Um eine hohe Codequalität und Wartbarkeit zu gewährleisten, wird eine pyramidale Teststrategie verfolgt: +## 6. Teststrategie & Symmetrie +Um eine hohe Codequalität und Wartbarkeit zu gewährleisten, wird eine pyramidale Teststrategie verfolgt. Dabei gilt das Prinzip der **Symmetrie**: Die Verzeichnisstruktur unter `tests/` spiegelt exakt die Struktur von `src/` wider, um die Auffindbarkeit von Tests sicherzustellen. ### Unit Tests (Logic Layer) - **Fokus**: Reine Geschäftslogik, Models, UseCases. - **Regel**: Diese Tests dürfen *keine* echte Datenbank oder externe APIs nutzen. Abhängigkeiten zur Data Layer werden zwingend durch Mocks/Doubles der Interfaces ersetzt. - **Ziel**: Schnelle Ausführung und vollständige Abdeckung der Edge-Cases in der Business-Logik. -### Integration Tests (Data & UI Layer) -- **Fokus**: Korrekte Persistenz (Repositories, Processor) und korrekte Endpunkt-Konfiguration (Controller, Handler). -- **Regel**: Nutzen eine echte Test-Datenbank oder einen In-Memory-Speicher. Hier wird geprüft, ob die Kommunikation zwischen den Schichten und zum Framework funktioniert. +### Integration Tests (Data Layer) +- **Fokus**: Korrekte Persistenz (Repositories, Processor) und Mapping. +- **Regel**: Nutzen eine echte Test-Datenbank oder einen In-Memory-Speicher. Hier wird geprüft, ob die technische Implementierung der Data-Layer korrekt funktioniert. -### Functional / E2E Tests -- **Fokus**: Durchlauf kompletter Business-Szenarien von der UI bis zur Data Layer. +### Functional Tests (UI Layer & Scenarios) +- **Fokus**: Durchlauf kompletter Business-Szenarien und Validierung von API-Endpunkten. +- **Werkzeug**: Einsatz des Symfony `WebTestCase`. +- **Ziel**: Sicherstellung, dass die Kette UI $\rightarrow$ Logic $\rightarrow$ Data konsistent funktioniert. ## 7. Logging & Observability