Files
nexarch/workflow/docs/TESTSTRATEGIE.md
T
patrickandClaude Sonnet 5.5 df9581cf45
DB-Integrationstests / db-tests (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Successful in 38s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 3s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 2s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 12s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Failing after 29s
CI / Core-Modul (Build/Vet/Test) (pull_request) Successful in 39s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Successful in 2s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web (dms-browser) (push) Failing after 52s
CI / Web (pdf-viewer) (push) Failing after 37s
CI / Web (shl) (push) Failing after 8s
CI / Web (dms-browser) (pull_request) Failing after 55s
CI / Web (pdf-viewer) (pull_request) Failing after 39s
CI / Web (shl) (pull_request) Failing after 7s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Successful in 2s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Failing after 14s
common Pflichttest-Gate / pflichttest-gate (pull_request) Successful in 19m7s
Supply-Chain-Scan (Go) / govulncheck (push) Failing after 1m1s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Successful in 18m45s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Failing after 1m13s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Successful in 18m28s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Failing after 38s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Successful in 18m16s
Workflow-Pflichttest-Gate / pflichttest-gate (pull_request) Successful in 18m10s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 4s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Failing after 3s
workflow, connect: bearerauth aus common/bearerauth
Die beiden gleichen Kopien entfallen; common v0.2.2. Das Testpflicht-Muster
fuer bearerauth wandert vom workflow-Gate in das common-Gate.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 23:41:06 +01:00

12 KiB
Raw Blame History

NEXARCH Workflow – Teststrategie

Stand: 2026-10-16. Ticket: QA-01. Vorbild: Core QA-01 (docs/TESTSTRATEGIE-CORE.md, Fertig), dieselbe Struktur wie Mail (mail/docs/TESTSTRATEGIE-MAIL.md) und AI (ai/docs/TESTSTRATEGIE-AI.md) — fuer Workflow uebernommen und um die vier Teilbereiche ergaenzt, die dieses Modul tatsaechlich hat: Engine, Genehmigungen, Aufgaben, Routing.

1. Warum dieses Dokument existiert

archivdms (Vorgaengerprojekt) hatte 0 Tests fuer auth/storage/permissions.go bei insgesamt nur 2 _test.go-Dateien in ganz internal/; archivmail testete 2 von 18 Modulen. NEXARCH Core legte deshalb in QA-01 fest: Testpflicht fuer Auth, Tenant-Scoping und Zugriffspruefung ist ein Merge-Gate, keine Nachruestung. Workflow uebernimmt denselben Grundsatz — hier zusaetzlich konkret gemacht fuer die sicherheitsrelevanten Stellen, die Workflow tatsaechlich hat (Abschnitt 4), statt den Grundsatz nur zu wiederholen.

Workflow ist zum Zeitpunkt dieses Tickets kein Neubau mehr wie Mail bei dessen QA-01: Engine (ENG-01/ENG-03/ENG-04), Genehmigungen (APR-01 bis APR-04), Aufgaben (TSK-01/TSK-02) und Routing (RTE-01 bis RTE-05) existieren bereits mit eigenen _test.go-Dateien je Ticket. Dieses Dokument macht explizit, was bisher implizit je Ticket entschieden wurde, und schliesst die eine echte Luecke, die eine Durchsicht ergeben hat (Abschnitt 4, 7).

2. Testpyramide

Ebene Werkzeug Umfang
Unit go test (Standardbibliothek) Einzelne Funktionen/Typen ohne externe Abhaengigkeit, z. B. processdef.Parse-Validierung, routingrule.Rule.Matches, delegation-Zeitraumlogik
Integration go test gegen echte PostgreSQL-Instanz (testdb.Pool, eigenes Schema je Testlauf) Repository-/Service-Schicht: statemachine.Engine, approval.Service, dualcheck.Service, task.Store, routingrule.Store — alle bestehenden *_test.go in internal/* folgen bereits diesem Muster
Vertragstest (Modulgrenze) go test gegen moduleadapter-HTTP-Schnittstelle (ENG-02), echter httptest.Server-Roundtrip DMS/Mail rufen Workflow ausschliesslich ueber internal/moduleadapter auf; moduleadapter_test.go/handler_test.go sind die bestehende Grundlage. Ein modulübergreifender Vertragstest mit echten DMS-/Mail-Konsumenten (analog archive-contract-tests.yml/contract-tests.yml) ist noch nicht eingerichtet, siehe Abschnitt 7
E2E Echter HTTP-Roundtrip ueber cmd/workflow-app (main_test.go startet den echten Mux) bis zum ersten Workflow-Frontend-Ticket, danach Playwright/Jest gegen die echten UIs (web/task-board, web/workflow-approvals, web/routing-rules, web/workflow-cases) Vollstaendiger Request-Response-Zyklus, kein reiner Funktionsaufruf

E2E-Zwischenloesung begruendet: Dieselbe Begruendung wie bei Mail — ein echter HTTP-Roundtrip ueber den tatsaechlich gestarteten Dienst (cmd/workflow-app, kein reiner In-Process-Aufruf) ist die ehrliche Untergrenze, bis die UI-Tickets fertig sind und Playwright/Jest eine echte Oberflaeche zum Testen haben.

3. Beispieltests je Testart und Bereich (Akzeptanzkriterium 1)

Kein Wegwerf-Demo — Verweis auf real existierende, bereits gruene Tests je Bereich:

Bereich Unit Integration Vertrag/E2E
Engine internal/processdef/processdef_test.go (Schema-Validierung) internal/statemachine/statemachine_test.go, history_test.go (Zustandsautomat, Historie, optimistische Sperre) cmd/workflow-app/main_test.go
Genehmigungen internal/dualcheck/dualcheck_test.go (Regel-Logik ohne DB-Seiteneffekt, soweit isolierbar) internal/approval/approval_test.go, approval_delegation_test.go, internal/delegation/delegation_test.go internal/approvalapi/handler_test.go
Aufgaben — (Validierung in task.go wird integriert mitgetestet) internal/task/task_test.go internal/caseoverviewapi/caseoverviewapi_test.go (Aufgaben-Bezug in der Fallübersicht)
Routing internal/routingrule/routingrule_test.go (Matches-Bedingungsauswertung) internal/routingengine/routingengine_test.go, internal/routingsim/routingsim_test.go internal/routingruleapi/handler_test.go

Zusaetzlich fuer QA-01 real durchgefuehrt: internal/fixtureset/fixtureset_test.go saet den unter Abschnitt 5 beschriebenen Testdatenbestand ueber die echten Domaenen-Services in eine frische Testdatenbank und prueft das Ergebnis (siehe Abschnitt 6, Pruefung 2) — ein weiteres Integrationstest-Beispiel, das alle vier Bereiche in einem Lauf abdeckt.

4. Pflichttests als Merge-Gate fuer sicherheitsrelevanten Code (Akzeptanzkriterium 4)

Verbindlich fuer jeden Pull Request, der Dateien in einem der folgenden Pakete aendert — jede geaenderte .go-Datei muss von einer geaenderten oder neuen _test.go-Datei im selben Package begleitet sein, identisch zur Regel aus Core QA-01:

  • Auth-nahe Logik: workflow/internal/svcauth/ (Service-Token-Vergleich in konstanter Zeit), workflow/internal/moduleadapter/ (prueft X-Service-Token gegen svcauth.Equal — der tatsaechliche Durchsetzungspunkt), common/bearerauth/ (prueft das Bearer-Token der Frontends gegen die Core-JWKS; X-User-Id nur noch ueber den Uebergangsschalter; Gate im common-Modul)
  • Tenant-Scoping: workflow/internal/tenantregistryclient/ (fragt Core TEN-01, muss bei Fehler fail-closed bleiben), workflow/internal/backchannel/ und workflow/internal/backchannelapi/ (extern erreichbarer Eingang, der den Tenant-Slug vor jeder Aktion gegen die Registry verifiziert, VOR-06)
  • Zugriffspruefung (Vier-Augen/Vertretung): workflow/internal/dualcheck/ (APR-02, ErrSameAsCreator verhindert Selbstbestaetigung), workflow/internal/delegation/ (APR-04, ErrSelfSubstitution verhindert Selbst-Vertretung als Umgehung des Vier-Augen-Prinzips)

Diese sieben Pakete wurden bewusst ausgewaehlt, nicht ganz Engine/Genehmigungen/ Aufgaben/Routing: Business-Logik wie task.go oder routingengine.go ist bereits heute durchgaengig getestet (Abschnitt 3), aber kein Tenant-/Auth-Gate im engeren Sinn. Diese sieben Stellen sind es, weil sie entweder eine Identitaet pruefen (svcauth, moduleadapter, tenantregistryclient) oder eine Umgehung eines Zugriffskontrollmechanismus verhindern (dualcheck, delegation, backchannel/-api).

internal/pflichttestgate implementiert das Gate (Code-Kopie des Musters aus Core internal/pflichttestgate bzw. Mail mail/internal/pflichttestgate — Workflow ist ein eigenstaendiges Go-Modul und kann die anderen nicht importieren). .gitea/workflows/workflow-pflichttest-gate.yml fuehrt es gegen jeden PR-Diff aus, der Dateien unter workflow/** aendert.

Negativtest des Gates selbst (Pruefung 1 dieses Tickets): internal/pflichttestgate/gate_test.go simuliert Diffs mit geaenderten Dateien in allen sieben Paketen ohne begleitende Testdatei und erwartet je einen Verstoss; ein zusaetzlicher Fall prueft, dass eine begleitende _test.go-Datei das Gate bestehen laesst und ein nicht-sensibler Pfad ignoriert wird.

5. Testdatenbestand (Akzeptanzkriterium 2)

testdata/fixtures/*.json haelt einen realistischen, vollstaendig synthetischen Datenbestand fuer alle vier Bereiche, angelehnt an das tatsaechliche Szenario, fuer das Workflow gebaut wird (Kanzlei-Akte/Posteingang ueber DMS/Mail):

  • engine.json — zwei Prozessdefinitionen (dokumentfreigabe, fristsache) im ENG-03-Format plus seed_instances, die je Definition eine echte Instanz starten und mindestens einen Uebergang ausfuehren (reale workflow_instances-/ workflow_instance_history-Zeilen, keine reinen Definitionsstubs)
  • approvals.json — drei Genehmigungsaufgaben, zwei aktivierte Vier-Augen- Prozesstypen (dualcheck_process_types) und eine Vertretungsregel (delegation_rules)
  • tasks.json — drei Aufgaben (Person- und Gruppenzuweisung, alle drei Prioritaetsstufen, mit Modul-Referenzen auf DMS/Mail-Objekte)
  • routing.json — drei Routing-Regeln mit unterschiedlicher Prioritaet und allen drei Bedingungsoperatoren (equals, in) sowie beiden Aktionstypen

Anonymisierung: Personen/Gruppen sind durchgaengig Slugs (anwalt.weber, ra-fachangestellte.kowalski, team-scanstelle) statt Klarnamen oder E-Mail-Adressen; Aktenzeichen (AZ-2026-0142) und Posteingangs-IDs sind frei erfunden und folgen keinem echten Nummernkreis. internal/fixtureset/fixtureset_test.go (TestFixtures_ContainNoEmailLikePII) prueft automatisiert, dass keine der Fixture-Dateien ein @-Zeichen enthaelt — eine harte, maschinell pruefbare Untergrenze gegen versehentlich eingestreute E-Mail-Adressen oder aehnliche Kontaktdaten.

internal/fixtureset laedt die JSON-Dateien und saet sie ueber die echten Domaenen-Services (processdef.Registry, approval.Service, dualcheck.Rules, delegation.Store, task.Store, routingrule.Store) statt per Roh-SQL — die Fixtures durchlaufen damit dieselben Validierungen wie Produktionsdaten (z. B. ErrInvalidAssigneeType, Schema-Pruefung von processdef.Parse).

6. Verantwortlichkeit je Testebene (Akzeptanzkriterium 3)

Testebene Verantwortlich Wann
Unit Entwickler:in des Tickets Lokal vor jedem Commit
Integration (testdb/TEST_TENANT_DSN) Entwickler:in des Tickets Lokal vor jedem Commit; in CI bei jedem Push/PR (ci.yml-Aequivalent fuer Workflow, sobald eingerichtet — siehe Abschnitt 7)
Pflichttest-Gate (Abschnitt 4) CI (workflow-pflichttest-gate.yml), durchgesetzt unabhaengig vom Willen der Entwickler:in Automatisch bei jedem PR auf workflow/** — blockierend, kein Review-Ermessen
Vertragstest (moduleadapter) Modul-Owner Workflow gemeinsam mit DMS-/Mail-Owner Bei jeder Aenderung an der ENG-02-Schnittstelle
E2E / UI QA (zweite Person) nach jedem UI-Ticket, danach als Teil der Review-Checkliste Vor Abnahme eines UI-Tickets
Teststrategie-Dokument selbst Zweite Person (Gegenlesen), siehe Abschnitt 7 Einmalig vor Abnahme dieses Tickets, danach bei strukturellen Aenderungen

7. Pruefungen (real durchgefuehrt)

# Pruefung Ergebnis
1 Negativtest des Gates: Diff mit sicherheitsrelevanter Aenderung ohne Test schlaegt kontrolliert fehl bestanden — go test ./internal/pflichttestgate/... -v auf 204, alle vier Faelle (fehlender Test je der sieben Pakete, begleiteter Test, nicht-sensibler Pfad, alle sieben Pakete gleichzeitig) grün
2 Testdatenbestand enthaelt keine echten Personendaten bestanden — TestFixtures_ContainNoEmailLikePII automatisiert (kein @ in den Fixture-Dateien) plus manuelle Durchsicht aller vier JSON-Dateien: ausschliesslich Slugs, erfundene Aktenzeichen, keine realen Namen/Domains
3 Zweite Person kann Teststrategie ohne Rueckfragen anwenden offen — siehe Abschnitt 8; in dieser Session keine zweite Person verfuegbar

Zusaetzlich real ausgefuehrt (Grundlage fuer Abschnitt 3/5): go build ./..., go vet ./... und go test ./... -p 1 -count=1 fuer das gesamte Workflow-Modul auf Host 204 gegen dms_dev-Testinfrastruktur, inklusive internal/fixtureset/fixtureset_test.go (saet alle vier Fixtures real in eine frische Testdatenbank und prueft zusaetzlich, dass die Vier-Augen-Regel eine Selbstbestaetigung ablehnt und die Vertretungsregel korrekt auflöst).

8. Offene Punkte

  • Pruefung 3 (zweite Person liest gegen) ist noch nicht durchgefuehrt — erfordert eine echte zweite Person, nicht durch eine weitere Session ersetzbar.
  • Ein modulübergreifender Vertragstest mit echten DMS-/Mail-Konsumenten der moduleadapter-Schnittstelle (analog archive-contract-tests.yml/ contract-tests.yml) ist noch nicht eingerichtet; aktuell deckt moduleadapter_test.go die Schnittstelle nur aus Workflow-Sicht ab.
  • Es gibt noch kein eigenes workflow-ci.yml fuer Build/Vet/Test/Coverage des gesamten Moduls bei jedem Push (wie ci.yml es fuer Core/DMS/Connect tut) — nur das in diesem Ticket ergaenzte Pflichttest-Gate. Ausserhalb des Umfangs dieses Tickets (QA-01 ist Teststrategie + Merge-Gate fuer sicherheitsrelevanten Code, nicht allgemeines CI-Setup), aber als Folgeticket sinnvoll.