Files
michaelschiemer/backups/docs-backup-20250731125004/guidelines/TESTING-GUIDELINES.md
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

4.4 KiB

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:

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
// 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
// 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
#[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
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
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