Unit Testing Guide: Tests richtig schreiben und strukturieren
Unit Tests sind das Fundament stabiler Software. Sie finden Fehler früh, dokumentieren das erwartete Verhalten und geben Ihnen die Sicherheit, Code ohne Angst zu refactoren. In diesem Guide zeige ich Ihnen, wie Sie effektive Unit Tests schreiben, die Ihren Code wirklich absichern.
Was sind Unit Tests?
Unit Tests prüfen einzelne, isolierte Einheiten Ihres Codes. Eine Einheit kann eine Funktion, eine Methode oder eine Klasse sein. Im Gegensatz zu Integrationstests oder E2E-Tests testen Unit Tests nur einen kleinen Teil der Anwendung, ohne externe Abhängigkeiten wie Datenbanken oder APIs.
Das Ziel: Schnelles Feedback bei Änderungen am Code. Gute Unit Tests laufen in Millisekunden und zeigen sofort, wenn eine Änderung bestehendes Verhalten bricht.
Das AAA-Pattern: Struktur für jeden Test
Jeder gute Unit Test folgt dem AAA-Pattern. Diese Struktur macht Tests lesbar und verständlich:
Arrange (Vorbereiten)
Im ersten Schritt bereiten Sie alles vor, was der Test benötigt: Testdaten erstellen, Mocks konfigurieren, Objekte initialisieren.
Act (Ausführen)
Hier führen Sie die zu testende Aktion aus. Das ist typischerweise ein einzelner Methodenaufruf.
Assert (Prüfen)
Abschließend prüfen Sie, ob das Ergebnis den Erwartungen entspricht. Hier kommen Assertions wie expect() oder assertEquals() zum Einsatz.
Beispiel in Jest/TypeScript:
describe('calculateTotal', () => {
it('sollte die Summe aller Preise berechnen', () => {
// Arrange
const items = [
{ name: 'Produkt A', price: 10 },
{ name: 'Produkt B', price: 25 }
];
// Act
const result = calculateTotal(items);
// Assert
expect(result).toBe(35);
});
});
Die wichtigsten Unit Testing Frameworks
| Sprache | Framework | Besonderheiten |
|---|---|---|
| JavaScript/TypeScript | Jest | All-in-One Lösung, Snapshot Testing, gute TypeScript-Unterstützung |
| JavaScript/TypeScript | Vitest | Schneller als Jest, native ESM-Unterstützung, Vite-kompatibel |
| Java | JUnit 5 | Der Standard für Java, mit Mockito für Mocking |
| PHP | PHPUnit | Das etablierte Framework für PHP-Tests |
| Python | pytest | Einfache Syntax, mächtiges Plugin-System |
Best Practices für Unit Tests
1. Testen Sie Verhalten, nicht Implementierung
Ein häufiger Fehler: Tests prüfen, wie etwas implementiert ist, statt was es tut. Solche Tests brechen bei jedem Refactoring, obwohl sich das Verhalten nicht geändert hat. Konzentrieren Sie sich auf Eingaben und erwartete Ausgaben.
2. Ein Konzept pro Test
Jeder Test sollte genau ein Verhalten prüfen. Wenn ein Test fehlschlägt, wissen Sie sofort, was nicht funktioniert. Tests mit mehreren Assertions für verschiedene Verhaltensweisen sind schwerer zu debuggen.
3. Tests müssen unabhängig sein
Kein Test darf von einem anderen abhängen. Jeder Test muss für sich allein laufen können, in beliebiger Reihenfolge. Vermeiden Sie geteilten Zustand zwischen Tests und nutzen Sie beforeEach für die Initialisierung.
4. Aussagekräftige Testnamen
Der Testname sollte beschreiben, was getestet wird und welches Ergebnis erwartet wird. Ein guter Name liest sich wie eine Spezifikation: sollte_Fehler_werfen_wenn_Email_ungültig.
5. Mocking mit Bedacht einsetzen
Mocks sind nützlich, um externe Abhängigkeiten zu isolieren. Aber zu viel Mocking führt zu Tests, die die Implementierung spiegeln statt das Verhalten zu prüfen. Nutzen Sie Dependency Injection und mocken Sie nur das Nötigste.
Praxis-Tipp: Bevorzugen Sie jest.spyOn() gegenüber komplettem Mocken von Modulen. So behalten Sie das echte Verhalten und können gezielt einzelne Methoden überschreiben.
Test Coverage richtig interpretieren
Code Coverage zeigt, wie viel Prozent Ihres Codes durch Tests abgedeckt ist. Eine hohe Coverage ist gut, aber nicht das einzige Ziel. 100% Coverage bedeutet nicht, dass Ihr Code fehlerfrei ist.
Streben Sie 70-80% Coverage als Richtwert an. Wichtiger als die Zahl ist, dass kritische Geschäftslogik gut getestet ist. Triviale Getter/Setter brauchen keine eigenen Tests.
Häufige Fehler vermeiden
Zu komplexe Tests: Wenn ein Test selbst Logik enthält, die Fehler haben könnte, ist er zu komplex. Tests sollten trivial sein.
Tests ignorieren: Ein fehlschlagender Test, der mit skip oder xtest deaktiviert wird, ist ein Warnsignal. Entweder reparieren oder entfernen.
Keine Edge Cases: Testen Sie nicht nur den Happy Path. Was passiert bei leeren Arrays, null-Werten oder ungültigen Eingaben?
Tests nachträglich schreiben: Test Driven Development (TDD) führt oft zu besserem Code, weil Sie die API aus Nutzersicht designen. Versuchen Sie, Tests vor der Implementierung zu schreiben.
Fazit
Unit Tests sind eine Investition, die sich auszahlt. Sie fangen Fehler früh ab, dokumentieren das erwartete Verhalten und ermöglichen angstfreies Refactoring. Mit dem AAA-Pattern, aussagekräftigen Namen und dem Fokus auf Verhalten statt Implementierung schreiben Sie Tests, die wirklich helfen. Starten Sie klein, mit den kritischsten Funktionen, und bauen Sie Ihre Testsuite schrittweise aus.
Testing-Strategie für Ihr Projekt?
Ich helfe Ihnen, eine Test-Suite aufzubauen, die Ihren Code zuverlässig absichert. Von der Strategie bis zur Implementierung.