Warum TDD in Rust nicht langweilig, sondern vorteilhaft ist?
\n\nHaben Sie jemals Code geschrieben, der „irgendwie richtig“ funktionierte, und dann einen Bug an der unerwartetsten Stelle gefunden? Kommt Ihnen bekannt vor. Testgetriebene Entwicklung (TDD) ist eine Methode, die den gewohnten Prozess auf den Kopf stellt. Anstatt zuerst Code zu schreiben und dann zu raten, ob er funktioniert, schreiben Sie zuerst einen Test, der fehlschlagen soll, und dann genau so viel Code, dass der Test besteht.
\n\nRust ist eine Sprache, die Sie bereits auf Compiler-Ebene vor einer ganzen Klasse von Fehlern schützt (Schluss mit Segfaults und Datenrennen!). Aber selbst der Compiler garantiert nicht, dass Ihre Logik korrekt ist. TDD in Rust fügt dieser Sicherheit eine weitere Ebene hinzu: Sie schreiben nicht nur Code, sondern dokumentieren das erwartete Verhalten direkt in den Tests. Und das ist unglaublich cool.
\n\nIn diesem Artikel werden wir TDD in Rust anhand praktischer Beispiele durchgehen. Sie werden sehen, wie Sie Tests vor der Implementierung schreiben, sie mit cargo test ausführen und Code umgestalten, ohne Angst haben zu müssen, etwas zu kaputt zu machen. Los geht's!
Was ist TDD und warum ist Rust dafür ideal?
\n\nTDD steht für Test-Driven Development (testgetriebene Entwicklung). Der Zyklus ist einfach und elegant:
\n\n- \n
- Rot – Wir schreiben einen Test, der eine neue Funktionalität beschreibt. Ausführen – der Test schlägt fehl (logisch, es gibt noch keinen Code). \n
- Grün – Wir schreiben minimalen Code, damit der Test besteht. Wir denken nicht an Schönheit, nur an das Bestehen des Tests. \n
- Refactoring – Wir verbessern den Code, ohne sein Verhalten zu ändern. Die Tests bleiben grün. \n
Rust ist aus mehreren Gründen ideal für TDD:
\n- \n
- Integriertes Testsystem –
cargo testfunktioniert sofort, keine externen Frameworks nötig. \n - Starke Typisierung – Der Compiler fängt Typfehler ab, die Tests logische Fehler. Zusammen sind sie unschlagbar. \n
- Besitz und Ausleihe – Tests helfen sicherzustellen, dass Sie korrekt mit dem Speicher umgehen, ohne unnötige Kopien zu erstellen. \n
- Community und Dokumentation – Die Rust-Community fördert das Testen aktiv, es gibt zahlreiche Beispiele. \n
Projekt für TDD einrichten
\n\nErstellen wir ein neues Projekt:
\ncargo new tdd_rust_example\ncd tdd_rust_example\n\nStandardmäßig erstellt cargo new eine Datei src/main.rs mit einem einfachen Programm. Wir werden eine Bibliothek schreiben, daher benennen wir sie in src/lib.rs um (oder löschen einfach main.rs und erstellen lib.rs). In Cargo.toml muss nichts geändert werden – die Tests sind bereits enthalten.
Übrigens, wenn Sie nur eine Bibliothek (ohne ausführbare Datei) schreiben, verwenden Sie cargo new --lib.
Erster Test: Rot
\n\nStellen Sie sich vor, wir möchten eine Funktion schreiben, die zwei Zahlen addiert. Nach TDD schreiben wir zuerst einen Test. Öffnen Sie src/lib.rs und fügen Sie hinzu:
#[cfg(test)]\nmod tests {\n #[test]\n fn test_add() {\n let result = add(2, 3);\n assert_eq!(result, 5);\n }\n}\n\nAusführen:
\ncargo test\n\nSie werden einen Kompilierungsfehler sehen – die Funktion add ist nicht definiert. Das ist normal. Wir sind in der roten Zone.
Grün: Minimale Implementierung
\n\nJetzt schreiben wir genau so viel Code, dass der Test besteht. Fügen Sie die Funktion add oberhalb des Testmoduls hinzu:
fn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n \n #[test]\n fn test_add() {\n let result = add(2, 3);\n assert_eq!(result, 5);\n }\n}\n\nBeachten Sie use super::*; – dies importiert alles aus dem übergeordneten Modul (unserem Code) in das Testmodul.
Führen Sie erneut cargo test aus. Grün! Der Test besteht. Wir haben das Minimum getan – die Summe zurückgegeben. Es scheint