This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Benjamin Admin 21a844cb8a fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00

4.9 KiB

Test-Regeln

Automatische Test-Erweiterung

WICHTIG: Bei JEDER Code-Aenderung muessen entsprechende Tests erstellt oder aktualisiert werden!

Wann Tests schreiben?

IMMER wenn du:

  1. Neue Funktionen erstellst → Unit Test
  2. Neue API-Endpoints hinzufuegst → Handler Test
  3. Bugs fixst → Regression Test (der Bug sollte nie wieder auftreten)
  4. Bestehenden Code aenderst → Bestehende Tests anpassen

Test-Struktur

Speicherort: Im gleichen Verzeichnis wie der Code

internal/
├── services/
│   ├── auth_service.go
│   └── auth_service_test.go    ← Test hier
├── handlers/
│   ├── handlers.go
│   └── handlers_test.go        ← Test hier
└── middleware/
    ├── auth.go
    └── middleware_test.go      ← Test hier

Test-Namenskonvention:

func TestFunctionName_Scenario_ExpectedResult(t *testing.T)

// Beispiele:
func TestHashPassword_ValidPassword_ReturnsHash(t *testing.T)
func TestLogin_InvalidCredentials_Returns401(t *testing.T)
func TestCreateDocument_MissingTitle_ReturnsError(t *testing.T)

Test-Template:

func TestFunctionName(t *testing.T) {
    // Arrange
    service := &MyService{}
    input := "test-input"

    // Act
    result, err := service.DoSomething(input)

    // Assert
    if err != nil {
        t.Fatalf("Expected no error, got %v", err)
    }
    if result != expected {
        t.Errorf("Expected %v, got %v", expected, result)
    }
}

Table-Driven Tests bevorzugen:

func TestValidateEmail(t *testing.T) {
    tests := []struct {
        name     string
        email    string
        expected bool
    }{
        {"valid email", "test@example.com", true},
        {"missing @", "testexample.com", false},
        {"empty", "", false},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := ValidateEmail(tt.email)
            if result != tt.expected {
                t.Errorf("Expected %v, got %v", tt.expected, result)
            }
        })
    }
}

Python Tests (Backend)

Speicherort: /backend/tests/

backend/
├── consent_client.py
├── gdpr_api.py
└── tests/
    ├── __init__.py
    ├── test_consent_client.py  ← Tests fuer consent_client.py
    └── test_gdpr_api.py        ← Tests fuer gdpr_api.py

Test-Namenskonvention:

class TestClassName:
    def test_method_scenario_expected_result(self):
        pass

# Beispiele:
class TestConsentClient:
    def test_check_consent_valid_token_returns_status(self):
        pass

    def test_check_consent_expired_token_raises_error(self):
        pass

Test-Template:

import pytest
from unittest.mock import AsyncMock, patch, MagicMock

class TestMyFeature:
    def test_sync_function(self):
        # Arrange
        input_data = "test"

        # Act
        result = my_function(input_data)

        # Assert
        assert result == expected

    @pytest.mark.asyncio
    async def test_async_function(self):
        # Arrange
        client = MyClient()

        # Act
        with patch("httpx.AsyncClient") as mock:
            mock_instance = AsyncMock()
            mock.return_value = mock_instance
            result = await client.fetch_data()

        # Assert
        assert result is not None

Test-Kategorien

1. Unit Tests (Hoechste Prioritaet)

  • Testen einzelne Funktionen/Methoden
  • Keine externen Abhaengigkeiten (Mocks verwenden)
  • Schnell ausfuehrbar

2. Integration Tests

  • Testen Zusammenspiel mehrerer Komponenten
  • Koennen echte DB verwenden (Test-DB)

3. Security Tests

  • Auth/JWT Validierung
  • Passwort-Hashing
  • Berechtigungspruefung

Checkliste vor Abschluss

Vor dem Abschluss einer Aufgabe:

  • Gibt es Tests fuer alle neuen Funktionen?
  • Gibt es Tests fuer alle Edge Cases?
  • Gibt es Tests fuer Fehlerfaelle?
  • Laufen alle bestehenden Tests noch? (go test ./... / pytest)
  • Ist die Test-Coverage angemessen?

Tests ausfuehren

# Go - Alle Tests
cd consent-service && go test -v ./...

# Go - Mit Coverage
cd consent-service && go test -cover ./...

# Python - Alle Tests
cd backend && source venv/bin/activate && pytest -v

# Python - Mit Coverage
cd backend && pytest --cov=. --cov-report=html

Beispiel: Vollstaendiger Test-Workflow

Wenn du z.B. eine neue GetUserStats() Funktion im Go Service hinzufuegst:

  1. Funktion schreiben in internal/services/stats_service.go
  2. Test erstellen in internal/services/stats_service_test.go:
    func TestGetUserStats_ValidUser_ReturnsStats(t *testing.T) {...}
    func TestGetUserStats_InvalidUser_ReturnsError(t *testing.T) {...}
    func TestGetUserStats_NoConsents_ReturnsEmptyStats(t *testing.T) {...}
    
  3. Tests ausfuehren: go test -v ./internal/services/...
  4. Dokumentation aktualisieren (siehe Dokumentation)