Warum TDD nicht nur eine weitere modische Methodik ist, sondern Ihr neuer Superhelden-Umhang
Stellen Sie sich vor: Sie schreiben Code wie ein Künstler – Strich für Strich, Zeile für Zeile. Sie sind überzeugt, dass alles genial ist. Aber eine Stunde vergeht, Sie starten die Anwendung, und sie stürzt mit einem Fehler ab, den Sie einen halben Tag lang gesucht hätten. Kommt Ihnen bekannt vor?
Stellen Sie sich nun ein anderes Szenario vor. Sie schreiben zuerst einen Test, der garantiert fehlschlägt. Dann – den minimalen Code, damit der Test besteht. Und erst dann – refaktorieren Sie, verbessern, aber mit gutem Gewissen. Das ist testgetriebene Entwicklung (TDD), und in Kotlin wird sie zu einem wahren Vergnügen.
In diesem Artikel werden wir keine langweiligen Vorträge halten. Wir nehmen ein reales Beispiel, durchlaufen alle drei Phasen von TDD (Red – Green – Refactor) und zeigen, wie man zuverlässigen Code ohne Angst und Tadel schreibt. Bereit? Los geht's!
TDD: Drei Buchstaben, die Ihren Code verändern werden
TDD (Test-Driven Development) ist nicht nur eine Technik, es ist eine Philosophie. Die Essenz ist einfach: zuerst der Test, dann der Code. Klingt verrückt? Auf den ersten Blick – ja. In der Praxis spart es Stunden des Debuggens.
Der Entwicklungszyklus durch Tests
- Red – wir schreiben einen Test, der nicht bestanden wird (er muss fehlschlagen).
- Green – wir schreiben den minimalen Code, damit der Test bestanden wird.
- Refactor – wir verbessern den Code, ohne sein Verhalten zu ändern.
Und so – im Kreis, in kleinen Schritten. Jeder Schritt ist die Gewissheit, dass Sie nichts kaputt gemacht haben. In Kotlin mit seiner prägnanten Syntax und Null-Sicherheit wird TDD noch angenehmer.
Werkzeuge: Was Sie für TDD in Kotlin brauchen
Bevor wir in den Code eintauchen, bereiten wir unser Arsenal vor. Für Unit-Testing in Kotlin benötigen Sie:
- JUnit 5 – der De-facto-Standard für Modultests.
- MockK – eine Bibliothek für Mocks, die speziell für Kotlin entwickelt wurde (keine Probleme mehr mit null und companion object).
- Gradle oder Maven – zur Verwaltung von Abhängigkeiten.
Fügen Sie in build.gradle.kts hinzu:
dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testImplementation("io.mockk:mockk:1.13.8")}Fertig. Jetzt können Sie Code schreiben, den Sie Ihren Kollegen zeigen können.
Den ersten TDD-Zyklus schreiben: Ein Taschenrechner mit Ambitionen
Beginnen wir mit einem Klassiker – einem Taschenrechner. Aber nicht einem einfachen, sondern mit Unterstützung für String-Operationen. Aufgabe: Die Funktion calculate nimmt einen String wie "2 + 3" entgegen und gibt 5 zurück.
Schritt 1: Red – einen fehlschlagenden Test schreiben
Erstellen Sie eine Testklasse:
import org.junit.jupiter.api.Testimport org.junit.jupiter.api.Assertions.assertEquals
class CalculatorTest {
@Test fun `should add two numbers`() { val calculator = StringCalculator() val result = calculator.calculate("2 + 3") assertEquals(5, result) }}Starten Sie – der Test schlägt fehl, weil die Klasse StringCalculator noch nicht existiert. Rotes Signal – alles läuft nach Plan.
Schritt 2: Green – minimaler Code zum Bestehen
Schreiben Sie genau so viel, dass der Test bestanden wird. Keine architektonischen Spielereien:
class StringCalculator { fun calculate(expression: String): Int { val parts = expression.split(" + ") return parts[0].toInt() + parts[1].toInt() }}Jetzt ist der Test grün. Hurra! Aber der Code ist noch hässlich – er ist nur auf die Addition zweier Zahlen ausgelegt.
Schritt 3: Refactor – den Code schön machen
Refaktorieren Sie, aber ändern Sie das Verhalten nicht. Fügen Sie Unterstützung für verschiedene Operationen hinzu, lagern Sie die Logik in separate Funktionen aus:
class StringCalculator { fun calculate(expression: String): Int { val (a, op, b) =