Testen in Rust: Frameworks und Werkzeuge
Rust ist eine systemnahe Programmiersprache, die großen Wert auf Zuverlässigkeit und Sicherheit des Codes legt. Das integrierte Testsystem ermöglicht es Entwicklern, Unit-Tests, Integrationstests und Dokumentationstests zu schreiben, ohne zusätzliche Bibliotheken installieren zu müssen. Für komplexe Szenarien – Parametrisierung, Generierung zufälliger Daten oder Mocking – hat die Rust-Community jedoch leistungsstarke Frameworks entwickelt. In diesem Artikel werden wir die wichtigsten Testwerkzeuge in Rust behandeln.
Das integrierte Modul test
Rust wird mit dem integrierten Modul test ausgeliefert, das über das Attribut #[test] aktiviert wird. Zum Ausführen der Tests wird der Befehl cargo test verwendet. Beispiel eines einfachen Unit-Tests:
// src/lib.rspub fn add(a: i32, b: i32) -> i32 { a + b}
#[cfg(test)]mod tests { use super::*;
#[test] fn test_add() { assert_eq!(add(2, 2), 4); }
#[test] fn test_add_negative() { assert_eq!(add(-1, 1), 0); }}Wichtige Funktionen des integrierten Moduls:
- Attribute:
#[test],#[ignore],#[should_panic]. - Assertions-Makros:
assert!,assert_eq!,assert_ne!. - Integrationstests: werden im Ordner
tests/abgelegt und testen die öffentliche API. - Dokumentationstests: Codebeispiele in Doc-Kommentaren, die über
cargo testgeprüft werden.
Für die meisten Projekte reicht dies aus. Wenn jedoch Parametrisierung, Generierung zufälliger Daten oder Mocking erforderlich sind, kommen spezialisierte Frameworks zum Einsatz.
Das Framework rstest – parametrisierte Tests
Die Bibliothek rstest bietet einen leistungsstarken Mechanismus zur Parametrisierung von Tests, ähnlich wie pytest in Python. Sie ermöglicht die Angabe mehrerer Sätze von Eingabedaten und erwarteten Ergebnissen ohne Code-Duplizierung.
Installation:
[dev-dependencies]rstest = "0.22"Beispiel eines parametrisierten Tests:
use rstest::rstest;
#[rstest]#[case(1, 2, 3)]#[case(0, 0, 0)]#[case(-1, 1, 0)]fn test_add(#[case] a: i32, #[case] b: i32, #[case] expected: i32) { assert_eq!(add(a, b), expected);}Funktionen von rstest:
- Parametrisierung über
#[case]. - Generierung zufälliger Daten über
#[random]. - Kontextbezogene Fixtures über
#[fixture]. - Unterstützung für asynchrone Tests.
Dieses Framework ist besonders nützlich beim Testen von mathematischen Funktionen, Parsern oder Algorithmen, bei denen viele Grenzfälle überprüft werden müssen.
Property-based Testing mit proptest
Property-based Testing (eigenschaftsbasiertes Testen) ist eine Methode, bei der Sie Invarianten (Eigenschaften) beschreiben, die für alle möglichen Eingabedaten gelten müssen. Die Bibliothek proptest generiert zufällige Eingabedaten und überprüft diese Eigenschaften.
Installation:
[dev-dependencies]proptest = "1.5"Beispiel: Überprüfung, dass eine Sortierung die Länge und alle Elemente beibehält:
use proptest::prelude::*;
proptest! { #[test] fn test_sort_keeps_elements(mut vec: Vec<i32>) { let original_len = vec.len(); let mut sorted = vec.clone(); sorted.sort(); assert_eq!(sorted.len(), original_len); for item in &vec { assert!(sorted.contains(item)); } }}Vorteile von proptest:
- Automatische Generierung tausender zufälliger Szenarien.
- Minimierung (Shrinking) – bei Testfehlern wird die
Auch in der Bibliothek
JWT-Token in Swift: Arbeiten mit JSON Web Token auf iOS/macOS
Überwachung von Swift-Anwendungen: Bibliotheken für iOS und macOS
Aufgabenplaner in C++: Task Scheduler von Grund auf erstellen
Arbeiten mit CSV in C# (.NET): Vollständige Anleitung