Testen in Rust: Unit-, Integrations- und E2E-Tests – vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Tests in Rust einfach und zuverlässig sind

Rust wurde von Anfang an als Sprache entwickelt, die beim Schreiben von sicherem und zuverlässigem Code hilft. Allerdings garantiert selbst das strengste Typsystem nicht die Korrektheit der Geschäftslogik. Hier kommen Tests zur Rettung. In Rust ist der Prozess des Schreibens von Tests direkt in die cargo-Toolchain integriert, was ihn unglaublich praktisch und zugänglich macht.

In diesem Artikel behandeln wir drei Testebenen: Unit-, Integrations- und E2E-Tests (End-to-End). Sie lernen, wie man Tests schreibt, wann man welchen Ansatz verwendet und wie man die Überprüfung Ihres Codes automatisiert. Das Material ist sowohl für Anfänger als auch für erfahrene Entwickler nützlich, die auf Rust umsteigen.



Unit-Tests: Testen von innen

Unit-Tests sind die grundlegendste und häufigste Testart. Sie überprüfen einzelne Funktionen, Methoden oder Module isoliert vom Rest des Systems. In Rust ist es üblich, Unit-Tests direkt in derselben Datei wie den zu testenden Code oder in einer separaten tests.rs-Datei innerhalb des Moduls zu schreiben.



So schreiben Sie Unit-Tests in Rust

Um einen Test zu erstellen, verwenden Sie das Attribut #[test]. Tests werden in einem Modul mit dem Attribut #[cfg(test)] platziert, das sicherstellt, dass der Testcode nicht in den endgültigen Build einbezogen wird.

// src/lib.rspub fn add(a: i32, b: i32) -> i32 {    a + b}

pub fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("Division durch Null")) } else { Ok(a / b) }}

#[cfg(test)]mod tests { use super::*;

#[test] fn test_add() { assert_eq!(add(2, 3), 5); }

#[test] fn test_add_negative() { assert_eq!(add(-1, 1), 0); }

#[test] fn test_divide_success() { let result = divide(10.0, 2.0); assert!(result.is_ok()); assert_eq!(result.unwrap(), 5.0); }

#[test] fn test_divide_by_zero() { let result = divide(10.0, 0.0); assert!(result.is_err()); assert_eq!(result.unwrap_err(), "Division durch Null"); }}


Unit-Tests ausführen

Sie können Tests mit einem einzigen Befehl ausführen:

cargo test

Die Ausgabe zeigt, wie viele Tests bestanden und wie viele fehlgeschlagen sind. Um einen bestimmten Test auszuführen, verwenden Sie einen Filter:

cargo test test_add

Unit-Tests sind ideal zum Überprüfen von Randfällen, Fehlerbehandlung und Algorithmenkorrektheit. Sie sind schnell und benötigen keine externen Abhängigkeiten.



Integrationstests: Überprüfung der Modulinteraktion

Integrationstests überprüfen, wie verschiedene Module Ihrer Bibliothek oder Anwendung zusammenarbeiten. Im Gegensatz zu Unit-Tests haben sie keinen Zugriff auf interne Funktionen (es sei denn, diese werden als pub exportiert). Integrationstests werden in einem separaten tests/-Ordner auf der Stammebene des Projekts geschrieben.



Struktur von Integrationstests

Erstellen Sie einen tests/-Ordner im Stammverzeichnis Ihres Projekts und fügen Sie Testdateien hinzu. Jede Datei wird als separate Crate kompiliert.

// tests/integration_test.rsuse my_crate; // Name Ihrer Crate

#[test]fn test_add_integration() { assert_eq!(my_crate::add(10, 20), 30);}

#[test]fn test_divide_integration() { let result = my_crate::divide(100.0, 4.0); assert_eq!(result.unwrap(), 25.0);}


Gemeinsames Modul für Tests

Wenn mehrere Integrationstests dieselben Hilfsfunktionen verwenden, extrahieren Sie diese in ein gemeinsames Modul. Erstellen Sie dazu einen Ordner tests/common/mod.rs:

// tests/common/mod.rspub fn setup() {    // Initialisierung von Logger, Datenbank usw.    println!("Testumgebung wird eingerichtet...");}

// tests/another_test.rsmod common;

#[test]fn test

Blogs

Buchempfehlungen