Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
13 KiB
Testphasen – MABEA V1
Bezug: 22_testkonzept, 18_version_1, 02_prozess_kontrolle, 03_fehlbestandsmanagement, 04_mindermengen, 05_rollen_rechte, 17_mobile_offline, 21_api.
Grundprinzip: Tests werden phasenweise aufgebaut, parallel zur Implementierung – nicht als Block am Ende. Jede Phase hat Einstiegs- und Abnahmekriterien. Der Satelliten-Betrieb (Karte 13) ist bewusst nicht Teil der V1-Testphasen, sondern eigene spätere Phase S (Roadmap).
Phase 0 – Testinfrastruktur (vor erstem Feature-Code)
Ziel: Gerüst steht, bevor Logik entsteht – verhindert „Tests schreiben wir später".
- pytest + pytest-asyncio + httpx (AsyncClient für FastAPI) im Projekt
- pytest-cov mit Regressions-Gate:
--cov-fail-under=50als Startwert inpytest.ini(Erfahrungswert: lieber niedrig starten und hochschrauben als gar kein Gate) - Separate Test-Datenbank (eigene PostgreSQL-Datenbank, Schema via Alembic-Migrationen aufgesetzt, nie gegen Dev-/Produktiv-DB)
- Test-Fixtures: frische DB pro Testklasse (Transaction-Rollback oder Drop/Create), Standard-Stammdaten-Set (1 Bereich, 2 Standorte, 3 Objekttypen, ~10 Materialien aller 3 Typen, 1 Vorlage mit Positionen, 2 Objekte, 4 Benutzer = 1 je Rolle)
- CI-Job (Gitea Actions): install → migrate → pytest → Coverage-Report; Blocker bei Rot
- Seed-Datensatz
systemknoten:objekt.zustaendiger_server_id,kontrolle.erzeugt_von_server_id,fehlbestand.erzeugt_von_server_id,historie.erzeugt_von_server_idsind NOT NULL (Prompt 20) – V1 braucht daher zwingend einen Seed-Datensatzsystemknoten (typ='haupt')VOR dem ersten Datensatz jeder Art, plus eine Konfigurations-Referenz im Backend (z. B. Umgebungsvariable/Settings-WertSYSTEMKNOTEN_ID), die der Anwendungscode bei jedem Insert einsetzt. Ohne diesen Seed schlägt der allererste Insert fehl – gehört in die Migrations-/Setup-Reihenfolge von Phase 0, nicht erst bei Satelliten-Umsetzung (Phase S) relevant.
Abnahmekriterium: pytest läuft grün (auch wenn erst 1 Smoke-Test existiert), CI schlägt bei Testfehler fehl.
Phase 1 – Domänenlogik (Unit-Tests, keine API, keine UI)
Ziel: Die fachlichen Leitplanken sind bewiesen, bevor irgendein Endpoint existiert. Reine Python-Tests gegen den Service-Layer (Prompt 19 Punkt 2), DB über Fixtures.
Kritischste Regeln zuerst (aus reihenfolge.md und Prompt 03/04):
| # | Test | Herkunft |
|---|---|---|
| U1 | Fehlbestand entsteht automatisch bei Ist < Soll | Prompt 02.3 |
| U2 | Mindermengen-Genehmigung ändert NIEMALS Ist-Menge und setzt Fehlbestand NIEMALS auf erledigt | Leitplanke, Prompt 04.1 |
| U3 | Fehlbestand → erledigt AUSSCHLIESSLICH wenn Ist = Soll (nie manuell) | Prompt 03.3 |
| U4 | Sofort-Nachfüllung in Kontrolle: Fehlbestand entsteht + wird erledigt, 2 Historieneinträge | Karte 07 |
| U5 | Teilnachfüllung: Status nachgefuellt_teilweise, Fehlmenge reduziert, zählt weiter als offen |
Prompt 03/12 |
| U6 | Genehmigung läuft bei nächster Kontrolle des Objekts automatisch ab | Karte 08, Prompt 04.4 |
| U7 | Genehmigung + Behebung vor nächster Kontrolle → beides gemeinsam beendet | Prompt 04.4 |
| U8 | Soll-Auflösung: Override auf Objektposition schlägt Vorlagenwert; Vorlagenänderung wirkt nur auf Positionen ohne Override | Prompt 10 |
| U9 | Duplizieren: Struktur/Soll ja, Ist/SN/Chargen/Fehlbestände/Historie nein, neuer Code | Prompt 09 |
| U10 | Vorlagenänderung erzeugt neue Version, alte Version bleibt lesbar (Snapshot-Historie) | Prompt 08 |
| U11 | Kontrolle abschließen mit unbestätigten Positionen → Fehler | Prompt 16.1 |
| U12 | Abgebrochene Kontrolle: keine Ist-Übernahme, kein Fehlbestand, Objekt bleibt unkontrolliert | Prompt 16.6 |
| U13 | Überbestand (Ist > Soll): protokolliert, aber KEIN Fehlbestand | Prompt 02.4 |
| U14 | Historie ist append-only: jeder fachliche Schritt erzeugt Eintrag mit wer/wann/alt→neu | Prompt 13 |
Einstiegskriterium: Phase 0 fertig. Abnahmekriterium: U1–U14 grün, Coverage Service-Layer ≥ 80 % (Domänenlogik ist der sicherheitskritische Kern).
Phase 2 – API-Integrationstests (HTTP gegen Test-DB)
Ziel: Jeder Endpoint aus Prompt 21 verhält sich spezifikationsgemäß, inkl. Rollenmatrix und Fehlerfälle.
- Auth: Login ok/falsch (401), Token abgelaufen,
auth/meliefert korrekte Rollen - Rollenmatrix (Prompt 05): parametrisierter Test – jede Rolle × jede kritische Aktion → erwarteter Status (200er/403). Das ist EIN Test mit Tabelle, deckt Matrix vollständig ab
- Fehlerfälle aus Prompt 21.9: Genehmigung ohne Begründung → 422; Genehmigung durch Mitarbeiter → 403; Abschluss mit offenen Positionen → 409 + Liste; Code-Duplikat beim Anlegen/Duplizieren → 409
- Idempotenz PUT Kontrollposition: derselbe PUT zweimal gesendet → identischer Endzustand, kein doppelter Fehlbestand (Vorbereitung Prompt 17)
- Zuständigkeitsfilter (Karte 04): Verantwortlicher sieht nur Fehlbestände seines Bereichs, Administration alles
- Objekt-Sperre (Prompt 02.8): Kontrolle auf Objekt A aktiv → zweiter Benutzer bekommt „wird kontrolliert von …", Übernahme erzeugt Historieneintrag; parallele Kontrollen auf Objekt B bleiben möglich
- Admin-API (7a): Benutzer/Zuständigkeiten/Kontrollverantwortung anlegen, ändern, löschen
Einstiegskriterium: Phase 1 grün. Abnahmekriterium: alle Endpunkte aus Prompt 21 durch Tests abgedeckt, Gesamt-Coverage ≥ 50 % (Gate greift).
Phase 3 – Prozess-Szenarien (E2E über API, komplette fachliche Ketten)
Ziel: Die 17 Testfälle aus 22_testkonzept als durchspielbare Szenarien – hier wird bewiesen, dass die Einzelteile zusammenwirken.
- S1–S17 = exakt die Testfälle 1–17 aus Prompt 22 (Normalfall, Fehlbestand, Sofort-Nachfüllung, Nachfüllung später, Teilnachfüllung, Dauer-offen, Genehmigung, Ablauf Genehmigung ×2, Ablaufdatum, Duplizieren, Override, Vorlagenänderung mit Override, Rollenmatrix, Historie-Kette, Kurzzeit-Netzausfall, Abbruch)
- Besonderheit S15 (Historie-Kette): komplette Kette aus Prompt 13.3 durchlaufen und Reihenfolge + Referenzen aller Historieneinträge prüfen
- Besonderheit S16 (Netzausfall): clientseitig simuliert – PUT zweimal absetzen bzw. verzögert, Server-Verhalten muss identisch sein
Einstiegskriterium: Phase 2 grün. Abnahmekriterium: S1–S17 grün, zweimal reproduzierbar (kein Flaky).
Phase 4 – Frontend/PWA-Tests
Ziel: Die Einsatzumfeld-Anforderungen (Prompt 11, 17) sind bewiesen.
- Kurzzeit-Netzausfall: Eingabe wird lokal gepuffert, nach Reconnect automatisch übertragen, Abschluss blockiert solange ungesendete Positionen existieren (Prompt 17.3) – Browser-Test mit Netzwerk-Throttling/Offline-Toggle (Playwright)
- Responsivität: Kernscreens (Screen 1–6) auf PC + Tablet + Smartphone-Viewport bedienbar, Touch-Ziele groß genug
- Fortschrittsanzeige + Gerätewechsel: Kontrolle auf Gerät 1 begonnen, auf Gerät 2 fortgesetzt (login-/objektgebunden, Karte 06)
- Statusfarben/Markierungen: genehmigte Mindermenge, individuelle Abweichung, Ablaufdatum-Warnung sichtbar unterscheidbar
- Manuelle Explorations-Session: 2–3 Praktiker aus dem Rettungsdienst klicken ohne Anleitung durch eine Kontrolle – Beobachtung dokumentieren (UX-Fallen)
Einstiegskriterium: Phase 3 grün, PWA bedienbar auf Test-Deployment. Abnahmekriterium: Netzausfall-Test grün, keine kritischen UX-Befunde offen.
Phase 5 – Pilotphase mit Echtdaten (organisatorisch, kein Code-Test)
Ziel: Realitätsabgleich, bevor Papier abgeschaltet wird.
- Testdaten aus den echten Excel-Listen (Handball Rucksack.xlsx, Rettungsrucksack.xlsx, Rucksack PAX SEG.xlsx im Repo) als initiale Vorlagen/Materialstamm importieren (Mapping siehe Abschnitt „Excel-Import-Mapping" unten)
- 1–2 Wochen Parallelbetrieb: Kontrolle digital UND Papier wie bisher, danach Abgleich (findet das System alles, was Papier fand?)
- Dedizierte Übungskontrollen mit vorher verabredeten Abweichungen („versteckte Fehlmenge") – prüft, ob Mitarbeiter den digitalen Weg korrekt durchlaufen
- E-Mail-Benachrichtigung (Karte 05) mit realem Mailserver verifizieren
- Feedback-Runde → kleinteilige UI-Nachjustierung
Einstiegskriterium: Phase 4 grün, Echtdaten importiert, Test-Deployment erreichbar. Abnahmekriterium (Go/No-Go für V1): Parallelbetrieb ohne fachliche Diskrepanz, keine Datenverluste, Akzeptanz bei Pilotnutzern vorhanden.
Excel-Import-Mapping (Detail zu Phase 5)
Grundlage: die drei bestehenden Listen im Repo (Handball Rucksack.xlsx, Rettungsrucksack.xlsx, Rucksack PAX SEG.xlsx), Struktur laut Ausgangsanalyse (Prompt 01): Fach-Überschriftzeile, darunter Zeilen mit Artikel/Menge/Artikelnummer, teils Seriennummer-Spalte.
Mapping-Tabelle
| Excel-Spalte/Struktur | Ziel im Datenmodell (Prompt 06/20) | Hinweis |
|---|---|---|
| Datei selbst (z. B. „Handball Rucksack") | objekttyp.name + beladungsvorlage.name (z. B. „Rucksack Handball Standard") |
Ein Import-Lauf pro Datei erzeugt einen Objekttyp + eine Vorlage Version 1 |
| Fach-Überschriftzeile (z. B. „Fach 1") | vorlagenposition.fach |
Freitext übernehmen wie in Excel geschrieben, keine Normalisierung nötig |
| Artikel-Spalte | material.name (neu anlegen, falls Name noch nicht im Materialstamm existiert) |
Abgleich über Artikelnummer, nicht über Namensgleichheit (Tippfehler-Gefahr) |
| Artikelnummer-Spalte | material.artikelnummer |
Primärer Abgleichsschlüssel beim Import: gleiche Artikelnummer über mehrere Listen hinweg → derselbe Materialstamm-Eintrag, nicht dubliziert anlegen |
| Menge-Spalte | vorlagenposition.sollmenge |
Numerisch parsen, Fehleinträge (z. B. „ca. 5") vor Import manuell bereinigen |
| Seriennummer-Spalte (falls vorhanden) | Materialtyp-Erkennung: Vorhandensein einer SN-Spalte bei dieser Zeile → material.materialtyp = 'geraet_sn', sonst 'standard' |
Ablaufdatum/Charge kommt in den bestehenden Listen nicht vor → für diese drei Listen entfällt Typ ablauf_charge beim Erstimport, wird später manuell ergänzt (z. B. Infusionssysteme) |
| Einheit | nicht in Excel vorhanden | Beim Import Standardwert „Stück" setzen, danach manuell korrigieren wo nötig (z. B. „Paar", „Packung") |
| Kategorie/Bereich | nicht in Excel vorhanden | Einmalig vor Import anlegen: 1 Bereich „Rettungsdienst/KatS", grobe Kategorie „Rucksäcke" für alle drei Objekttypen |
Ablauf des Imports (Vorschlag, Umsetzung Phase 5)
- Bereich + Kategorie einmalig anlegen (Administration, manuell oder Skript).
- Je Excel-Datei: Objekttyp + Beladungsvorlage Version 1 anlegen.
- Zeilen einlesen (stdlib
zipfile/xml.etree.ElementTreewie bei der Erstanalyse, siehe Prompt 01 – keinopenpyxlnötig): Fach, Artikel, Artikelnummer, Menge, optionale SN-Spalte. - Je Zeile: Material anhand Artikelnummer suchen oder neu anlegen, dann Vorlagenposition mit Sollmenge und Fach erzeugen.
- Konkrete Objekte (z. B. „Rucksack Handball 12", „Rucksack Handball 17") werden NICHT aus Excel importiert (Excel enthält nur die Soll-Struktur, keine konkreten Instanzen) – Administration legt sie danach manuell an, je mit Code (Karte 10) und Vorlagen-Referenz.
- Erste Kontrolle je neu angelegtem Objekt erfasst den tatsächlichen Ist-Bestand (Objekte starten „nicht kontrolliert", analog Duplizieren-Regel Prompt 09) – dies IST der Übergang vom Papier- zum Digitalbetrieb (Prompt 23).
Bekannte Lücken, vor Import zu klären
- Einheiten pro Material sind in den Excel-Listen nicht erfasst – vor Import Liste durchgehen und einmalig ergänzen (einmaliger manueller Aufwand, keine Systemfrage).
- Uneindeutige/fehlende Artikelnummern in den Quell-Listen (falls vorhanden) verhindern automatischen Abgleich – in diesen Fällen manuelle Zuordnung beim Import nötig.
- Import-Skript selbst ist Code (Prompt-19-Deployment-Regel gilt: bei Umsetzung nur Skript-Datei erzeugen, Ausführung gegen Test-DB erst auf Zielsystem/Test-Deployment, nicht lokal).
Regeln übergreifend
- Kein Feature ohne Test: jeder Endpoint/jede Domänenregel wird erst mit Test gemerged (CI-Gate).
- Leitplanke-Doppelschutz: U2/U3 (Mindermenge ≠ erledigt) laufen zusätzlich als Phase-3-Szenario (S7) – bei Bruch dieser Regel sofortiger Release-Blocker.
- Coverage-Hochschraubung: nach V1-Release Gate schrittweise 50 → 60 → 70 % erhöhen.
- Testdaten niemals Produktivdaten: Pilotphase läuft auf Test-Deployment, echte Inbetriebnahme erst nach Go/No-Go.
Phase S – Satelliten-Betrieb (spätere Erweiterung, NICHT V1)
Roadmap-Phase, erst nach stabiler V1. Eigener Testplan nötig, mindestens:
- PoC mit zwei lokalen PostgreSQL-Instanzen (Docker oder zwei Datenbanken): Objekt auslagern → Kontrolle + Fehlbestand + Nachfüllung + Genehmigung am „Satelliten" → zurücksyncen → Hauptserver-Stand vollständig und ohne Duplikate
- Sync-Fälle 1–3 aus Prompt 20.10 einzeln beweisen (Insert neue Zeilen, Upsert Objektpositionen, Upsert Fehlbestand/Genehmigung)
- Bestückungsregel testen: Objekt mit offenem Fehlbestand auslagern → am Satelliten nachfüllen → zurücksyncen → genau EIN Fehlbestand, erledigt
- Schreibzugriff am Hauptserver auf ausgelagertes Objekt → muss abgelehnt werden
- Offene Punkte aus Karte 13 vorher entscheiden: Pre-Sync-Check laufender Kontrollen, DB-Trigger für
zuletzt_geaendert_am, Bestückungs-Details
Referenzen
Bezug: 22_testkonzept, 18_version_1, 01_anforderungsanalyse, 09_duplizieren, 23_papieraloesung, 13_satelliten_server