chore: complete update
This commit is contained in:
181
docs/guidelines/TESTING-GUIDELINES.md
Normal file
181
docs/guidelines/TESTING-GUIDELINES.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Testing-Richtlinien
|
||||
|
||||
## Übersicht
|
||||
|
||||
Diese Richtlinien beschreiben die Standards und Best Practices für Tests im Framework.
|
||||
|
||||
## Grundprinzipien
|
||||
|
||||
### 1. Testarten
|
||||
|
||||
- **Unit Tests**: Testen einzelner Komponenten isoliert
|
||||
- **Integrationstests**: Testen des Zusammenspiels mehrerer Komponenten
|
||||
- **Funktionstests**: Testen ganzer Funktionalitäten aus Benutzersicht
|
||||
|
||||
### 2. Pest-Framework
|
||||
|
||||
Alle Tests werden mit dem Pest-Framework geschrieben:
|
||||
|
||||
```php
|
||||
test('Analytics::track zeichnet Events korrekt auf', function () {
|
||||
// Arrange
|
||||
$manager = new AnalyticsManager(['enabled' => true], new InMemoryStorage());
|
||||
$analytics = new Analytics($manager, new EventDispatcher());
|
||||
|
||||
// Act
|
||||
$analytics->track('test_event', ['key' => 'value']);
|
||||
|
||||
// Assert
|
||||
expect($manager->getStorage()->retrieve())->toHaveCount(1);
|
||||
expect($manager->getStorage()->retrieve()[0]['event'])->toBe('test_event');
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Teststruktur
|
||||
|
||||
- Jeder Test folgt dem AAA-Prinzip: Arrange, Act, Assert
|
||||
- Tests sollten unabhängig voneinander sein
|
||||
- Tests sollten deterministisch sein (keine zufälligen Ergebnisse)
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Testabdeckung
|
||||
|
||||
- Jede öffentliche Methode sollte getestet werden
|
||||
- Edge Cases und Fehlersituationen explizit testen
|
||||
- Fokus auf Business-Logik und kritische Pfade
|
||||
|
||||
### 2. Mocking
|
||||
|
||||
- Externe Abhängigkeiten mocken
|
||||
- Eigene Test-Implementierungen für Interfaces erstellen
|
||||
- Mock-Objekte nur für die spezifischen Testfälle konfigurieren
|
||||
|
||||
```php
|
||||
// Beispiel: Test mit Mock
|
||||
test('Fehlerbehandlung bei Storage-Ausfall', function () {
|
||||
// Arrange
|
||||
$storage = new class implements StorageInterface {
|
||||
public function store(array $events): void
|
||||
{
|
||||
throw new \RuntimeException('Storage-Fehler');
|
||||
}
|
||||
|
||||
public function retrieve(array $filters = []): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
$manager = new AnalyticsManager(['enabled' => true], $storage);
|
||||
|
||||
// Act & Assert
|
||||
expect(fn() => $manager->flush())->toThrow(\RuntimeException::class);
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Fixtures und Factories
|
||||
|
||||
- Testdaten mit Factories erstellen
|
||||
- Komplexe Objekte über Helpers aufbauen
|
||||
- Wiederverwendbare Fixtures für ähnliche Tests
|
||||
|
||||
```php
|
||||
// Beispiel: Test-Factory
|
||||
function createAnalyticsManager(array $config = []): AnalyticsManager
|
||||
{
|
||||
$defaultConfig = ['enabled' => true, 'auto_flush' => false];
|
||||
return new AnalyticsManager(
|
||||
array_merge($defaultConfig, $config),
|
||||
new InMemoryStorage()
|
||||
);
|
||||
}
|
||||
|
||||
test('Auto-Flush funktioniert korrekt', function () {
|
||||
// Arrange
|
||||
$manager = createAnalyticsManager(['auto_flush' => true, 'batch_size' => 2]);
|
||||
|
||||
// Act
|
||||
$manager->track('event1', []);
|
||||
$manager->track('event2', []);
|
||||
|
||||
// Assert
|
||||
expect($manager->getStorage()->retrieve())->toHaveCount(2);
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Datenbankzugriffe
|
||||
|
||||
- In Unit-Tests Datenbankzugriffe vermeiden oder mocken
|
||||
- In Integrationstests separate Testdatenbank verwenden
|
||||
- Testdatenbank nach Tests zurücksetzen
|
||||
|
||||
### 5. Asynchrone Tests
|
||||
|
||||
- Timeouts für asynchrone Tests setzen
|
||||
- Auf Async-Events warten, statt feste Wartezeiten
|
||||
|
||||
## Testorganisation
|
||||
|
||||
### 1. Dateistruktur
|
||||
|
||||
- Tests in `/tests`-Verzeichnis mit gleicher Struktur wie `/src`
|
||||
- Dateinamen mit `Test`-Suffix
|
||||
|
||||
### 2. Testgruppen
|
||||
|
||||
- Tests mit Attributen in Gruppen einteilen
|
||||
- Langsame Tests markieren
|
||||
|
||||
```php
|
||||
#[Group('analytics')]
|
||||
#[Group('slow')]
|
||||
test('große Datenmenge verarbeiten', function () {
|
||||
// Test mit vielen Daten
|
||||
});
|
||||
```
|
||||
|
||||
## CI/CD-Integration
|
||||
|
||||
- Tests in CI-Pipeline automatisiert ausführen
|
||||
- Testabdeckung messen und überwachen
|
||||
- Pull Requests nur mit erfolgreichen Tests mergen
|
||||
|
||||
## Fehlersuche
|
||||
|
||||
### 1. Debugging-Techniken
|
||||
|
||||
- Pest-Debugging aktivieren mit `->dump()`
|
||||
- PHPUnit-Assertions für detaillierte Fehlermeldungen
|
||||
|
||||
```php
|
||||
test('komplexes Objekt validieren', function () {
|
||||
$result = processData();
|
||||
|
||||
// Bei Fehlern Kontext ausgeben
|
||||
if (!expect($result->isValid())->toBeTrue()->isSuccess()) {
|
||||
dump($result->getErrors());
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Problematische Tests
|
||||
|
||||
- Flaky Tests identifizieren und beheben
|
||||
- Tests isolieren mit `only` oder `skip`
|
||||
|
||||
```php
|
||||
test('problematischer Test', function () {
|
||||
// Test-Code
|
||||
})->skip('Wird untersucht');
|
||||
```
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
- Tests sind ein integraler Bestandteil der Codebase
|
||||
- Qualität und Wartbarkeit der Tests sind genauso wichtig wie die des Produktionscodes
|
||||
- Tests dienen als lebende Dokumentation der Funktionalität
|
||||
Reference in New Issue
Block a user