Files
Benjamin Boenisch e22019b2d5 Add CLAUDE.md, MkDocs docs, .claude/rules
- CLAUDE.md: Comprehensive documentation for Lehrer KI platform
- docs-src: Klausur, Voice, Agent-Core, KI-Pipeline docs
- mkdocs.yml: Lehrer-specific nav with blue theme
- docker-compose: Added docs service (port 8010, profile: docs)
- .claude/rules: testing, docs, open-source, abiturkorrektur, vocab-worksheet, multi-agent, experimental-dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:49:25 +01:00

4.9 KiB

Test-Regeln

Automatische Test-Erweiterung

WICHTIG: Bei JEDER Code-Änderung müssen entsprechende Tests erstellt oder aktualisiert werden!

Wann Tests schreiben?

IMMER wenn du:

  1. Neue Funktionen erstellst → Unit Test
  2. Neue API-Endpoints hinzufügst → Handler Test
  3. Bugs fixst → Regression Test (der Bug sollte nie wieder auftreten)
  4. Bestehenden Code änderst → 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 für consent_client.py
    └── test_gdpr_api.py        ← Tests für 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 (Höchste Priorität)

  • Testen einzelne Funktionen/Methoden
  • Keine externen Abhängigkeiten (Mocks verwenden)
  • Schnell ausführbar

2. Integration Tests

  • Testen Zusammenspiel mehrerer Komponenten
  • Können echte DB verwenden (Test-DB)

3. Security Tests

  • Auth/JWT Validierung
  • Passwort-Hashing
  • Berechtigungsprüfung

Checkliste vor Abschluss

Vor dem Abschluss einer Aufgabe:

  • Gibt es Tests für alle neuen Funktionen?
  • Gibt es Tests für alle Edge Cases?
  • Gibt es Tests für Fehlerfälle?
  • Laufen alle bestehenden Tests noch? (go test ./... / pytest)
  • Ist die Test-Coverage angemessen?

Tests ausführen

# 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: Vollständiger Test-Workflow

Wenn du z.B. eine neue GetUserStats() Funktion im Go Service hinzufügst:

  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 ausführen: go test -v ./internal/services/...
  4. Dokumentation aktualisieren (siehe documentation.md)