# NEXARCH Mail – Teststrategie Stand: 2026-08-30. Ticket: QA-01. Vorbild: Core `QA-01` (`docs/TESTSTRATEGIE-CORE.md`, Fertig) — dieselbe Struktur, für das Mail-Modul übernommen, wo sinnvoll um protokollspezifische Aspekte (IMAP/SMTP/MIME) ergänzt. ## 1. Warum dieses Dokument existiert archivmail (Vorgängerprojekt) testete 2 von 18 Modulen trotz hoher Kritikalität (Compliance-/Protokoll-Logik). Kein zentrales Issue-Tracking — Bugs wurden nur als `BUG-N`-Kommentare im Code festgehalten (`known-issues-archivmail.md`). NEXARCH Mail übernimmt denselben Grundsatz wie Core: **Testpflicht für Auth, Tenant-Scoping und Protokoll-/Compliance-kritische Logik ist ein Merge-Gate, keine Nachrüstung.** ## 2. Testpyramide | Ebene | Werkzeug | Umfang | |---|---|---| | Unit | `go test` (Standardbibliothek) | Einzelne Funktionen/Typen, keine externe Abhängigkeit (DB, Netzwerk, IMAP/SMTP-Socket) | | Integration | `go test` gegen echte PostgreSQL-Instanz (`nexarch_test`-Rolle) | Repository-/Handler-Schicht, Tenant-Scoping, Objekt-Speicher | | Protokoll-Zustandsmaschinen | `go test` gegen echten IMAP-/SMTP-Client-Roundtrip (kein reiner Parser-Unit-Test) | ING-01/ING-02/ING-03: Login-Zustände, Befehlssequenzen, Fehlerpfade | | E2E | Echter HTTP-Roundtrip (`httptest.Server`) bis zum ersten Mail-Frontend-Ticket, danach Playwright/Jest gegen die echte UI | Vollständiger Request-Response-Zyklus, kein reiner Funktionsaufruf | | Vertragstests | Analog Core `QA-07`/DMS-Äquivalent, sobald Mail öffentliche Modul-Adapter-Schnittstellen (RET-05-Konsument, siehe `ARC-11`) hat | Wire-Contract-Stabilität | **E2E-Zwischenlösung begründet:** Mail hat aktuell kein Frontend-Ticket (0/66 Board). Playwright/Jest bräuchte eine echte Browser-UI zum Testen — bis zum ersten Mail-Frontend-Ticket ist ein echter HTTP-Roundtrip (kein reiner In-Process-Funktionsaufruf) die ehrliche, tatsächlich verfügbare Untergrenze für "E2E". Siehe Beispiel in Abschnitt 3. ## 3. Beispieltests je Testart (Akzeptanzkriterium/Pflichtprüfung 2) `mail/internal/example` — kein Wegwerf-Demo, sondern eine kleine, tatsächlich nützliche Funktion (E-Mail-Adress-Normalisierung), die spätere Ticket ohnehin brauchen: - **Unit:** `normalize_test.go` — `TestNormalizeAddress_*`, keine externe Abhängigkeit. - **Integration:** `store_integration_test.go` — `TestAddressStore_SaveAndCheckExists`, echte Postgres-Instanz, `TEST_TENANT_DSN`, `t.Cleanup`. - **E2E:** `handler_e2e_test.go` — `TestNormalizeHandler_RealHTTPRoundTrip`, echter `httptest.Server`-Roundtrip (TCP, nicht nur Funktionsaufruf). Alle sechs Tests real ausgeführt (siehe Prüfungen, Abschnitt 6). ## 4. Pflichttests als Merge-Gate (Akzeptanzkriterium 3/4) Verbindlich für jeden Pull Request, der Dateien in einem der folgenden Bereiche ändert: - **Auth** (`mail/internal/auth/` — sobald durch ein späteres Ticket angelegt) - **Tenant-Scoping** (`mail/internal/tenant/`, jede Repository-Schicht mit Mandanten-Bezug) - **Protokoll-kritisch** (`mail/internal/ingest/`, `mail/internal/imap/`, `mail/internal/smtp/` — Zustandsmaschinen, Auth-Handshakes der Protokolle selbst) - **Compliance-kritisch** (`mail/internal/arc/` oder gleichwertig — RET-05-Konsument, Löschung/Archivierung, siehe `ARC-11`) Regel (identisch zu Core `QA-01`): **jede geänderte `.go`-Datei in einem dieser Bereiche muss von einer geänderten oder neuen `_test.go`-Datei im selben Package begleitet sein.** `mail/internal/pflichttestgate` implementiert das Gate (Code-Kopie des Musters aus Core `internal/pflichttestgate`, mit mail-spezifischen Pfadmustern statt Core-Pfaden — bewusst keine Cross-Modul-Abhängigkeit, da Mail als eigenständiges Go-Modul Core nicht importieren kann). `.gitea/workflows/mail-pflichttest-gate.yml` führt es gegen jeden PR-Diff aus. Negativtest des Gates selbst (Prüfung 1 dieses Tickets): `mail/internal/pflichttestgate/gate_test.go` simuliert einen Diff mit geänderter `mail/internal/auth/login.go` ohne begleitende Testdatei und erwartet, dass das Gate das als Verstoß erkennt. ## 5. Bug-Tracking (Akzeptanzkriterium 3) **Konvention: Gitea-Issues** auf `gitea.perlbach24.de/scripte/nexarch`, Label `mail` plus Schweregrad-Label (`bug-kritisch`/`bug-normal`/`bug-kosmetisch`). Durchsuchbar über Gitea-Suche/Label-Filter — explizit KEIN Code-Kommentar-Tracking (`BUG-N` wie in archivmail), das laut `known-issues-archivmail.md` genau diese Sichtbarkeitslücke verursacht hat. **Realer Durchspiel-Nachweis (Prüfung 3):** Diese Session (nicht Mail-spezifisch, aber derselbe reale Vorgang) fand mehrere echte Bugs, dokumentiert nach exakt diesem Muster in den jeweiligen `*-PRUEFPROTOKOLL.md`-Dateien statt als Code-Kommentar, z. B. `archive/docs/RET-10-PRUEFPROTOKOLL.md`: fehlende CORS-Header bei RET-06-API, gefunden bei einer Sichtprüfung, Symptom (Browser hätte Fetch blockiert), Ursache (kein `Access-Control-Allow-Origin`), Fix (RET-10-Ticket), Nachweis (curl-Test vorher/ nachher) — alles durchsuchbar in der Protokolldatei, nicht im Quelltext verstreut. **Ehrlich vermerkt:** Ein ECHTER Gitea-Issue konnte in dieser Session nicht angelegt werden (kein Gitea-API-Token verfügbar, nur Git-SSH/HTTPS-Push-Zugriff). Das oben verlinkte Beispiel demonstriert das Vorgehen strukturell (Symptom → Ursache → Fix → Nachweis, durchsuchbar abgelegt), aber NICHT über die Gitea-Issue-Oberfläche selbst. Sobald ein Gitea-Zugriffstoken verfügbar ist, sollte mindestens ein Test-Issue real angelegt werden, um die Konvention vollständig nachzuweisen — offener Punkt, siehe Abschnitt 7. ## 6. Prüfungen (real durchgeführt) | # | Prüfung | Ergebnis | |---|---|---| | 1 | Dokument liegt vor und wurde von zweiter Person gegengelesen | **bestanden** — Dokument von der Nutzerin/dem Nutzer (zweite Person) gegengelesen und freigegeben (2026-08-30) | | 2 | Stichprobe: mindestens ein Beispieltest je benannter Testart ist umgesetzt | **bestanden** — 6 Tests real ausgeführt auf 131: `go test ./mail/internal/example/... -v -p 1`, alle grün (3 Unit, 1 Integration, 2 E2E) | | 3 | Bug-Tracking-Vorgehen wurde einmal exemplarisch für einen realen Befund durchgespielt | **teilweise bestanden** — Vorgehen strukturell durchgespielt anhand eines realen, bereits dokumentierten Befunds (RET-10), aber NICHT über die echte Gitea-Issue-Oberfläche (kein API-Token verfügbar). Siehe Abschnitt 5, offener Punkt in Abschnitt 7 | ## 7. Offene Punkte - Echter Gitea-Issue als Nachweis der Bug-Tracking-Konvention noch nicht angelegt (fehlendes API-Token in dieser Session). Sollte nachgeholt werden, sobald Zugriff besteht. - `mail/internal/auth/`, `mail/internal/tenant/`, `mail/internal/ingest/` etc. existieren noch nicht — die Pflichttest-Gate-Pfadmuster sind auf Basis der geplanten Modulstruktur vordefiniert, nicht an echtem Code verifiziert. Erste Nagelprobe: das erste Ticket, das einen dieser Pfade tatsächlich anlegt (voraussichtlich `ING-01`).