All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 32s
CI/CD / test-python-backend-compliance (push) Successful in 31s
CI/CD / test-python-document-crawler (push) Successful in 23s
CI/CD / test-python-dsms-gateway (push) Successful in 17s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s
- Backfill 81 controls with empty source_citation.source from generation_metadata - Add fallback to generation_metadata.source_regulation in ControlDetail blue box - Improve Rule 3 amber box text for reformulated controls - Add 30 new tests for batch processing (TestParseJsonArray, TestBatchSizeConfig, TestBatchProcessingLoop) — all 61 control generator tests passing - Fix stale test_config_defaults assertion (max_controls 50→0) - Update canonical-control-library.md with batch processing pipeline docs, processed chunks tracking, migration guide, and stats endpoint - Update testing.md with canonical control generator test section Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.1 KiB
6.1 KiB
Test-Regeln
Automatische Test-Erweiterung
WICHTIG: Bei JEDER Code-Aenderung muessen entsprechende Tests erstellt oder aktualisiert werden!
Wann Tests schreiben?
IMMER wenn du:
- Neue Funktionen erstellst → Unit Test
- Neue API-Endpoints hinzufuegst → Handler Test
- Bugs fixst → Regression Test (der Bug sollte nie wieder auftreten)
- 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:
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:
- Funktion schreiben in
internal/services/stats_service.go - 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) {...} - Tests ausfuehren:
go test -v ./internal/services/... - Dokumentation aktualisieren (siehe Dokumentation)
Modul-spezifische Tests
Canonical Control Generator (82 Tests)
Die Control Library hat eine umfangreiche Test-Suite ueber 6 Dateien. Siehe Canonical Control Library — Tests fuer Details.
# Alle Generator-Tests
cd backend-compliance && pytest -v tests/test_control_generator.py
# Similarity Detector Tests
cd backend-compliance && pytest -v compliance/tests/test_similarity_detector.py
# API Route Tests
cd backend-compliance && pytest -v tests/test_canonical_control_routes.py
# License Gate Tests
cd backend-compliance && pytest -v tests/test_license_gate.py
# CI/CD Validator Tests
cd backend-compliance && pytest -v tests/test_validate_controls.py
Wichtig: Die Generator-Tests nutzen Mocks fuer Anthropic-API und Qdrant — sie laufen ohne externe Abhaengigkeiten.
Die TestPipelineMocked-Klasse prueft insbesondere:
- Korrekte Lizenz-Klassifikation (Rule 1/2/3 Verhalten)
- Rule 3 exponiert keine Quellennamen in
generation_metadata - SHA-256 Hash-Deduplizierung fuer Chunks
- Config-Defaults (
batch_size: 5,skip_processed: true) - Rule 1 Citation wird korrekt mit Gesetzesreferenz generiert