Files
leocrm/docs/test-strategy.md
T
Agent Zero a4d0f0c35d
Check Cross-Plugin Imports / check (push) Has been cancelled
feat(D): Phase D — Undo/Restore komplett implementiert
- D-GEN: RestoreRegistry mit RestoreConfig (model_class, restore_permission, excluded_fields, special_handler)
- D-HOOK: history_hooks.py mit register_history_hooks() für after_create/update/delete
- D-CORE: Company create+update record_history in companies.py
- D-PLUG: Task/Calendar/DMS record_history in services/routes
- D-SOFT: Alle registrierten Entitäten haben deleted_at + un-delete via Registry
- D-MAIL: Mail special_handler (IMAP Trash-Move, Folder-Verify) + record_history in delete/move
- D-TRASH: GET /entity-history/trash (filterbar, paginiert) + Frontend Trash.tsx
- D-TOAST: UndoToast.tsx (5s Auto-Dismiss, useUndoToast Hook)
- D-HIST-UI: HistoryPanel.tsx (Timeline, Diff-View, Restore-Button)
- D-BULK: POST /entity-history/bulk-restore mit partial_success Semantik
- D-RET: POST /entity-history/retention/archive (GDPR hard-delete >90 Tage)
- D-TEST: 26 Tests in test_restore_registry.py, alle grün
- D-DOC: test-strategy.md + security_kernel.md aktualisiert

Backend: 10 Dateien, Frontend: 7 Dateien, Tests: 1 Datei, Docs: 3 Dateien
26/26 Tests passed, TSC 0 errors, App import 492 routes
2026-08-13 23:08:29 +02:00

13 KiB
Raw Blame History

LeoCRM Test-Strategie

Wichtig: Dieses Dokument muss nach jeder größeren Änderung am Codebase (neue Plugins, neue Module, Refactoring, Security-Änderungen) überarbeitet werden. Siehe leocrm-test-strategy.promptinclude.md.


1. Übersicht

LeoCRM verwendet eine mehrschichtige Test-Strategie um Funktionalität, Sicherheit und Stabilität sicherzustellen.

Test-Pyramide

        ┌──────────┐
        │   E2E    │  ← Browser-Tests (geplant, noch nicht implementiert)
        ├──────────┤
        │Integration│  ← pytest mit echter PostgreSQL/Redis Test-DB
        ├──────────┤
        │   Unit    │  ← pytest mit Mocks (teilweise)
        └──────────┘

Aktuelle Abdeckung

Ebene Tool Status Abdeckung
Backend-Tests pytest aktiv 69 Testdateien, ~500 Tests
Frontend-Tests vitest ⚠️ geplant 0 Tests (54k Zeilen ungetestet)
E2E-Tests Playwright/Cypress ⚠️ geplant 0 Tests
Security-Tests bandit, pip-audit ⚠️ geplant nicht implementiert
CI-Pipeline scripts/ci_pipeline.sh aktiv 15+ Checks

2. Backend-Tests (pytest)

Architektur

  • Test-DB: PostgreSQL leocrm_test (localhost:5432)
  • Redis: localhost:6379/0 (wird vor jedem Test geflushed)
  • Fixture-Strategie: Function-scoped (jeder Test bekommt frische DB)
  • Schema-Erstellung: Base.metadata.create_all (keine Alembic-Migrationen)
  • Plugin-Aktivierung: In-Memory-Registry muss pro Fixture gesetzt werden

Bekannte Einschränkungen

  1. RLS (Row Level Security) nicht testbar:

    • Die Test-DB verwendet create_all statt Alembic-Migrationen
    • RLS-Policies werden normalerweise durch Migrationen erstellt
    • RLS-Tests wurden ausgebaut (bringt nichts wenn es sich nicht testen lässt)
    • Lösung: Alembic-Migrationen in Test-DB ausführen (Roadmap)
  2. LLM-API-Tests blockieren:

    • Tests die externe LLM-APIs aufrufen (Ollama Cloud, OpenRouter) blockieren
    • Die komplette Suite hängt bei ~46% wenn LLM-Calls nicht gemockt sind
    • Lösung: LLM-Calls in Tests mocken (Roadmap)
  3. Fixture-Overhead (~2,5s pro Test):

    • seed_tenant_and_users (1,27s) + create_app (0,73s) + login (0,34s)
    • Wird pro Test ausgeführt (Function-Scope)
    • Session-Scope ist nicht möglich weil ~30 Testdateien seed_tenant_and_users direkt aufrufen
    • Lösung: Seed-Daten session-scopen + clean_tables anpassen (Roadmap)
  4. Keine Parallelisierung möglich:

    • pytest-xdist funktioniert nicht weil alle Worker dieselbe Test-DB teilen
    • Lösung: Pro-Worker Datenbank (Roadmap)

Test-Kategorien

Kategorie Beschreibung Beispiele
Funktionale Tests Testet ob Features funktionieren test_calendar, test_tags, test_dms
Permission-Tests Testet ABAC/Permission-System test_permissions, test_entity_permissions
Plugin-Tests Testet Plugin-Lifecycle und -Funktionen test_plugins, test_entity_links
Cross-Tenant-Tests Testet Tenant-Isolation test_cross_tenant_security
AI-Tests Testet AI-Proactive, Copilot, GraphRAG test_ai_proactive, test_ai_copilot
Integration-Tests Testet Modul-übergreifend test_unified_search, test_outbox

Konventionen

  1. Test-Dateien: tests/test_<modul>.py
  2. Fixtures: In tests/conftest.py definiert
  3. Plugin-Aktivierung: Jede Plugin-Test-Datei muss init_permission_registry(active_plugin_names={...}) aufrufen
  4. Entity-Typen: Verwende korrekte ENTITY_MODELS-Keys (z.B. file nicht dms_file, mail_account nicht mailbox)
  5. URLs: Verwende korrekte API-Pfade (z.B. /api/v1/entity-links/ nicht /api/v1/dms/)
  6. Dedup-Tests: Verwende unterschiedlichen Dateiinhalt pro Upload um Dedup-Logik nicht zu triggern
  7. Keine zufälligen UUIDs: Verwende echte Entity-IDs aus der DB, nicht uuid.uuid4()

3. Frontend-Tests (geplant)

Aktuell

  • 0 Tests für 54.000 Zeilen TSX/TypeScript
  • Frontend-Bugs werden nur manuell im Browser gefunden

Roadmap

  • Unit-Tests: vitest für React-Komponenten
  • Integration-Tests: Testing Library für Komponenten-Interaktionen
  • E2E-Tests: Playwright für kritische User-Flows (Login, Kontakt erstellen, Kalender)

4. Security-Testing (geplant)

Aktuell

  • Keine automatisierten Security-Tests
  • Security-Bugs wurden durch manuelle Code-Review gefunden (siehe Bugfix-Session 2026-08-12)

Bekannte Security-Lücken (behoben am 2026-08-12)

Bug Fix Status
MAIL_ENCRYPTION_KEY hatte Default-Wert RuntimeError wenn nicht gesetzt
revoke_permission ohne Owner-Check check_single_entity_access hinzugefügt
is_active=True hart codiert im DB-Fallback User-Status aus DB laden
Plugin-Gate allow bei fehlendem Tenant TODO - bricht Tests, muss in Produktion anders gelöst werden ⚠️
Public Share URL falsch URL korrigiert
Logout nur in Redis Auch PostgreSQL invalidieren
Rate-Limit nur auf IP Token-Hash für Bearer-Auth
RLS-Commit statt flush Alle Commits durch flush ersetzt
Webhook ohne Tenant-Context set_tenant_context hinzugefügt
npm ci || npm install Fallback Nur npm ci

Roadmap

  • bandit: Python Security-Scanner in CI-Pipeline
  • pip-audit: Dependency-Scanning
  • npm audit: Frontend-Dependency-Scanning
  • OWASP ZAP: Web-Application-Scanner gegen Test-Instanz
  • Security-Test-Suite: Eigene pytest-Tests für Security-Szenarien

5. CI/CD Pipeline

Aktuelle Checks (scripts/ci_pipeline.sh)

  1. Python Compile Check
  2. Cross-Plugin Import Check
  3. Alembic Revision Graph
  4. Alembic Migration Test (wenn DATABASE_URL gesetzt)
  5. Migration Hash Check
  6. TypeScript Type Check
  7. Frontend Build
  8. Test Collection
  9. Backend Tests
  10. Frontend Tests
  11. SQL Injection Check
  12. npm ci strict mode

Bekannte CI-Lücken

  • Smoke-Test gegen Build: Tests laufen gegen leocrm_test DB, nicht gegen den aktuellen Build
  • Frontend-Tests: vitest ist konfiguriert aber hat 0 Tests
  • Security-Scanning: bandit/pip-audit nicht in Pipeline
  • E2E-Tests: Nicht in Pipeline

6. Was getestet wird und was nicht

Wird getestet

  • API-Endpunkte (CRUD, Validierung, Permissions)
  • Plugin-Lifecycle (Install, Activate, Deactivate)
  • ABAC/Permission-System
  • Cross-Tenant-Isolation (ohne RLS)
  • AI-Proactive/GraphRAG (mit Mocks)
  • Outbox/Event-System
  • Backup/Restore
  • Auth/Login/Logout
  • Tags, Calendar, DMS, Mail, Contacts, Tasks

Wird NICHT getestet

  • Frontend (54k Zeilen, 0 Tests)
  • RLS-Policies (Test-DB hat keine RLS)
  • LLM-APIs (blockieren Suite, nicht gemockt)
  • Race Conditions (keine Last-Tests)
  • Security-Edge-Cases (SQL Injection nur oberflächlich)
  • Dockerfile/Deployment (nur Code, nicht Infrastruktur)
  • CI-Scripts selbst (Shell-Scripts nicht getestet)
  • Produktions-Logs (keine Log-Analyse)

7. Roadmap

Priorität Maßnahme Aufwand Nutzen
🔴 Hoch Frontend Unit-Tests (vitest) mittel 54k Zeilen abgedeckt
🔴 Hoch LLM-API-Calls mocken gering Suite läuft komplett durch
🟡 Mittel Security-Test-Suite mittel Security-Bugs automatisch gefunden
🟡 Mittel E2E-Tests (Playwright) hoch Kritische User-Flows getestet
🟡 Mittel Alembic-Migrationen in Test-DB mittel RLS testbar
🟡 Mittel Fixture-Optimierung (Session-Scope) hoch Suite 3x schneller
🟢 Niedrig bandit/pip-audit in CI gering Automatisches Security-Scanning
🟢 Niedrig Pro-Worker Test-DB mittel Parallelisierung möglich
🟢 Niedrig Log-Analyse Pipeline gering Produktions-Fehler erkannt

8. Wann muss dieses Dokument aktualisiert werden?

Dieses Dokument MUSS aktualisiert werden bei:

  1. Neue Plugins oder Module → Test-Kategorien und Abdeckung aktualisieren
  2. Security-Änderungen → Security-Lücken und Fixes dokumentieren
  3. Neue Test-Infrastruktur (z. B. vitest, Playwright) → Abschnitt hinzufügen
  4. CI-Pipeline-Änderungen → Checks und Lücken aktualisieren
  5. Größere Refactoring → Konventionen und Einschränkungen überprüfen
  6. Nach jeder Bugfix-Session → Bekannte Lücken und Fixes dokumentieren

Verantwortlich: Agent/Entwickler der die Änderung durchführt.


9. Historie

Datum Ereignis
2026-08-12 Test-Strategie erstellt nach Bugfix-Session (14 Security-Bugs, ~170 Testfehler behoben)
2026-08-13 Phase A Verifikation: 8-Check-Pipeline verbindlich, A-TEST Ergebnisse dokumentiert, RLS- und Test-Isolations-Probleme bestätigt

10. Verbindliche Test-Pipeline (8 Checks)

Diese Pipeline ist verbindlich für Phase-Gate-Reviews und muss vor jedem Phasenabschluss grün sein.

# Check Kommando Wann
1 Backend Tests python -m pytest -v --tb=short Einzel-Task + Block + Phase-Gate
2 Frontend Tests cd frontend && npx vitest run --reporter=verbose Einzel-Task + Block + Phase-Gate
3 TypeScript Check cd frontend && npx tsc --noEmit Einzel-Task + Block + Phase-Gate
4 E2E Tests cd frontend && npx playwright test (kritische Flows) Block + Phase-Gate
5 Frontend Build cd frontend && npm run build Block + Phase-Gate
6 Health Check curl /api/v1/health → 200 Phase-Gate (deployed)
7 Login Check Login → 200 Phase-Gate (deployed)
8 Cross-Tenant Test python -m pytest tests/test_cross_tenant_security.py Block + Phase-Gate

Staffelung

  • Einzel-Task: relevante Unit-/Integration-/Frontend-Tests + Typecheck/Build soweit betroffen
  • Größerer Block: Checks 15 + 8
  • Phase-Gate: alle 8 Checks inklusive Deploy/Health/Login

Phase A Verifikationsergebnisse (2026-08-13)

Check Ergebnis Hinweis
1. Backend Tests 145/145 (Auth/Resilience/Hooks/Contacts/Companies/Plugins) ⚠️ test_tenant.py: 15 Batch-Failures (DB-Lock-Konflikte, Einzeltests passen)
2. Frontend Tests 744/751 passed 7 Worker-Crashes (Resource-Limits im Container, nicht Test-Failures)
3. TypeScript Check 0 errors
4. E2E Tests Nicht ausgeführt Playwright nicht in dieser Umgebung verfügbar
5. Frontend Build 3.5s, 90 precache entries
6. Health Check 200 (Production: 33-74ms avg ~45ms)
7. Login Check 200 (Production: 22-63ms avg ~48ms)
8. Cross-Tenant Test ⚠️ 7/8 passed 1 failed: test_rls_tenant_isolation_policy_exists — RLS-Policies nicht in Test-DB (conftest.py nutzt create_all statt Alembic)

Bekannte Test-Infrastruktur-Probleme (Phase A bestätigt)

  1. RLS nicht testbarconftest.py nutzt Base.metadata.create_all statt Alembic-Migrationen. RLS-Policies aus Migration 0004/0078 werden nicht erstellt. test_rls_tenant_isolation_policy_exists schlägt fehl. Lösung: T-RLS Task (Alembic-Migrationen in Test-DB).

  2. Test-Isolationtest_tenant.py hat 15 Failures im Batch (DB-Lock-Konflikte bei TRUNCATE). Einzeltests passen. Lösung: Pro-Worker Datenbank (T-PARALLEL) oder Serial-Only-Mode.

  3. Vitest Worker-Crashes — 7 von 96 Test-Files crashen mit „Worker exited unexpectedly". Resource-Limits im Container. Lösung: --pool=forks oder Memory-Limit erhöhen.

  4. Vollständiger pytest-Lauf dauert >15min — 1401 Tests mit DB-Setup. Lösung: T-PARALLEL (pytest-xdist mit pro-Worker DB).


Phase D — Undo/Restore Test-Ergebnisse

Neue Test-Datei: tests/test_restore_registry.py (26 Tests)

Test-Gruppe Tests Status
RestoreRegistry (Singleton, Register, Get, List, Overwrite, Excluded Fields) 6
RestoreFromHistory (Unsupported type, History not found) 2
HistoryHooks (extract_entity_id, register, hook fires record_history) 6
TrashList (Returns delete entries, Entity type filter) 2
BulkRestore (All success, Partial failure, All fail) 3
Retention (Returns count, Zero when none) 2
SensitiveFieldsExclusion (Default, Contact, DMS, Mail, All registered) 5

Verifizierte Aspekte

  • RestoreRegistry: Nur explizit registrierte Entity-Typen können restored werden
  • Excluded Fields: id, tenant_id, timestamps, search_tsv, embedding werden nie restored
  • Entity-spezifische Exclusions: Contact (relationship IDs), DMS (storage_path, content_hash), Mail (message_id, raw_path)
  • Mail Special Handler: IMAP-Semantik (Trash-Move, Folder-Verify, kein falscher lokaler Status)
  • Bulk Restore: Partial-Failure-Semantik (partial_success Flag, per-item results)
  • Retention: GDPR-Hard-Delete nach konfigurierbarer Aufbewahrungsfrist
  • Hook-based History: do_action('entity.after_create/update/delete')record_history()
  • Dynamic Permission Checks: Restore-Permission aus RestoreConfig, nicht hardcoded