# 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

### Go Tests (Consent Service)

**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:**

```go
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:**

```go
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:**

```go
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:**

```python
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:**

```python
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

```bash
# 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`:
   ```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](./documentation.md))
