Testgetriebene Entwicklung
TDD ist der Rot-Grün-Zyklus. Diese Fähigkeit ist die Referenz, die diesen Zyklus dazu bringt, Tests zu produzieren, die es wert sind, behalten zu werden: was einen guten Test ausmacht, wo Tests hingehören, die Anti-Patterns und die Regeln des Zyklus. Jeder Abschnitt gilt in jedem Zyklus: konsultieren Sie sie vor und während des Zyklus, nicht danach.
Wenn Sie die Codebasis erkunden, lesen Sie CONTEXT.md (falls vorhanden), damit Testnamen und Schnittstellen-Vokabular mit der Fachsprache des Projekts übereinstimmen, und respektieren Sie ADRs in dem Bereich, den Sie bearbeiten.
Was einen guten Test ausmacht
Tests verifizieren Verhalten durch öffentliche Schnittstellen, nicht durch Implementierungsdetails. Code kann sich komplett ändern; Tests sollten das nicht. Ein guter Test liest sich wie eine Spezifikation: „Benutzer kann mit gültigem Warenkorb auschecken“ sagt Ihnen genau, welche Fähigkeit existiert, und er überlebt Refactorings, weil ihn die interne Struktur nicht interessiert.
Siehe tests.md für Beispiele und mocking.md für Mocking-Richtlinien.
Seams: wo Tests hingehören
Ein Seam ist die öffentliche Grenze, an der Sie testen: die Schnittstelle, an der Sie Verhalten beobachten, ohne ins Innere zu greifen. Tests leben an Seams, niemals gegen Interna.
Testen Sie nur an vorab vereinbarten Seams. Bevor Sie einen Test schreiben, notieren Sie die zu testenden Seams und bestätigen Sie diese mit dem Benutzer. Kein Test wird an einem unbestätigten Seam geschrieben. Sie können nicht alles testen. Daher legt die Vereinbarung der Seams im Voraus fest, dass der Testaufwand auf die kritischen Pfade und die komplexe Logik fällt, statt auf jeden Randfall.
Fragen Sie: „Was ist die öffentliche Schnittstelle, und welche Seams sollten wir testen?“
Wenn die Form dieser Schnittstelle selbst in Frage steht (wie tief das Modul ist, wo der Seam hingehört, was die Schnittstelle exponieren sollte), rufen Sie das Skill-Tool mit „codebase-design“ für das Vokabular auf. Es ist die gemeinsame Quelle der Begriffe Modul, Schnittstelle, Tiefe, Seam, Adapter, Hebelwirkung und Lokalität, und es ist eine Referenz zum Konsultieren, keine Sitzung zum Ausführen.
Anti-Patterns
- Implementierungsgekoppelt: mockt interne Kollaborateure, testet private Methoden oder verifiziert über einen Seitenkanal (Abfragen der Datenbank anstelle der Schnittstelle). Der Hinweis: der Test bricht bei einem Refactoring, obwohl sich das Verhalten nicht geändert hat.
- Tautologisch: die Assertion berechnet den erwarteten Wert auf die gleiche Weise wie der Code (
expect(add(a, b)).toBe(a + b), ein Snapshot, der auf die gleiche Weise von Hand abgeleitet wurde, eine Konstante, die mit sich selbst gleichgesetzt wird). Dadurch besteht er konstruktionsbedingt und kann niemals vom Code abweichen. Erwartete Werte müssen aus einer unabhängigen Wahrheitsquelle stammen: einem bekannten guten Literal, einem durchgerechneten Beispiel, der Spezifikation. - Horizontales Slicing: zuerst alle Tests schreiben, dann die gesamte Implementierung. Massentests verifizieren vorgestelltes Verhalten: Sie testen die Form der Dinge statt des benutzerseitigen Verhaltens, die Tests werden unempfindlich gegenüber echten Änderungen, und Sie verpflichten sich auf eine Teststruktur, bevor Sie die Implementierung verstehen. Arbeiten Sie stattdessen in vertikalen Scheiben: ein Test → eine Implementierung → wiederholen, jeder Test ein Tracer Bullet, der auf das reagiert, was der letzte Zyklus Sie gelehrt hat.
Regeln des Zyklus
- Rot vor Grün. Schreiben Sie zuerst den fehlschlagenden Test, dann nur genug Code, um ihn zu bestehen. Antizipieren Sie keine zukünftigen Tests und fügen Sie keine spekulativen Features hinzu.
- Eine Scheibe nach der anderen. Ein Seam, ein Test, eine minimale Implementierung pro Zyklus.
- Refactoring ist nicht Teil des Zyklus. Es gehört zur Review-Phase (siehe die Fähigkeit
matt-code-review), nicht zum Rot-Grün-Implementierungszyklus.