Einleitung: Warum schreiben wir Bugs und beheben sie dann heldenhaft?
\n\nHaben Sie jemals Code geschrieben, der "irgendwie normal" funktionierte, und dann, drei Tage später, einen Bug gefunden, der alles zum Einsturz brachte? Wenn ja – willkommen im Club. Wenn nein – Sie sind entweder ein C++-Gott oder haben einfach noch nie Produktivcode ausgeführt.
\n\nTestgetriebene Entwicklung (TDD) ist keine Modediät für Programmierer. Es ist eine Disziplin, die den Prozess des Code-Schreibens auf den Kopf stellt. Anstatt zuerst die Logik zu schreiben und dann hektisch zu überlegen, wie man sie testet, machen wir es umgekehrt: zuerst der Test, dann der Code. Klingt verrückt? Vielleicht. Aber genau so entsteht Code, den man seinen Kollegen zeigen kann und der am Freitagabend nicht kaputt geht.
\n\nIn diesem Artikel werden wir TDD in C++ anhand realer Beispiele durchgehen: Wir schreiben eine einfache Bibliothek für Fibonacci-Zahlen unter Verwendung des Red-Green-Refactor-Zyklus. Sie werden sehen, wie TDD nicht nur hilft, Bugs zu vermeiden, sondern auch Schnittstellen zu entwerfen.
\n\nWas ist TDD und warum ist C++ ohne TDD wie ohne Bremsen?
\n\nTDD (Test-Driven Development) ist eine Entwicklungsmethodik, bei der zuerst ein Test geschrieben wird, der bewusst fehlschlägt (Red), dann der minimale Code geschrieben wird, der den Test bestehen lässt (Green), und schließlich ein Refactoring (Refactor) durchgeführt wird, um die Struktur zu verbessern, ohne das Verhalten zu ändern.
\n\nWarum ist das gerade für C++ wichtig? Weil C++ eine Sprache ist, in der man sich leicht ins Bein schießen kann: undefiniertes Verhalten, Speicherlecks, falsche Typumwandlungen. TDD erzeugt automatisch ein Sicherheitsnetz, das Fehler zur Kompilier- und Laufzeit abfängt.
\n\nDer Red-Green-Refactor-Zyklus: Wie er funktioniert
\n\n- \n
- Red: Wir schreiben einen Test, der fehlschlagen soll. Das ist unsere "Anforderung" an den Code. \n
- Green: Wir schreiben den minimalen Code, damit der Test bestanden wird. Kein Over-Engineering! \n
- Refactor: Wir verbessern den Code (Doppelungen entfernen, Logik vereinfachen) – die Tests bleiben grün. \n
Klingt einfach? Ja. Aber in der Praxis erfordert es Disziplin. Lassen Sie es uns versuchen.
\n\nWerkzeuge für TDD in C++: Google Test vs Catch2
\n\nBevor wir Code schreiben, wählen wir ein Test-Framework. Zwei Hauptkandidaten:
\n\n- \n
- Google Test – leistungsstark, beliebt, mit vielen Makros. Ideal für große Projekte. \n
- Catch2 – leicht, modern, mit praktischer Syntax. Perfekt für Lernbeispiele und Microservices. \n
In diesem Artikel verwenden wir Catch2 (v3), weil es minimalistisch ist und keine zusätzlichen Einstellungen erfordert. Aber wenn Sie Google Test bevorzugen – die TDD-Prinzipien sind dieselben.
\n\nPraxis: TDD für Fibonacci-Zahlen schreiben
\n\nStellen wir uns vor, wir müssen eine Funktion fibonacci(int n) schreiben, die die n-te Fibonacci-Zahl zurückgibt (0-te = 0, 1-te = 1, 2-te = 1, 3-te = 2 usw.).
Schritt 1: Red – Wir schreiben einen Test, der fehlschlägt
\n\nErstellen wir eine Datei test_fib.cpp:
#define CATCH_CONFIG_MAIN\n#include <catch2/catch_test_macros.hpp>\n\n// Die Funktion ist noch nicht deklariert – das ist in Ordnung\nint fibonacci(int n);\n\nTEST_CASE("Fibonacci-Zahlen", "[fib]") {\n REQUIRE(fibonacci(0) == 0);\n REQUIRE(fibonacci(1) == 1);\n REQUIRE(fibonacci(2) == 1);\n REQUIRE(fibonacci(10) == 55);\n}\n\nWir versuchen zu kompilieren – wir erhalten einen Linker-Fehler. Der Test ist RED. Perfekt!
\n\nSchritt 2: Green – Wir schreiben den minimalen Code, damit der Test bestanden wird
\n\nErstellen wir eine Datei fib.cpp:
int fibonacci(int n) {\n if (n <= 1) return n;\n return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nWir kompilieren und führen die Tests aus. Bestehen sie? Ja, aber das ist ineffizient. Unser Ziel ist jedoch Green, nicht Perfektion. Vorerst lassen wir es so.
\n\n