BDD in Rust: Lebendigen Code mit Cucumber und Specs schreiben

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

Warum BDD in Rust nicht nur langweilige Tests bedeutet

\n\n

Stellen Sie sich vor: Sie entwickeln in Rust einen hochbelasteten Dienst. Der Code ist sicher, schnell, aber wenn das Produkt zum Kunden kommt, sagt dieser: „Ich dachte, der Knopf sollte anders funktionieren.“ Kommt Ihnen das bekannt vor? Die klassische Kluft zwischen Code und Erwartungen. Genau hier kommt BDD (Behaviour-Driven Development) ins Spiel – eine Methodik, die Geschäftsanforderungen in eine Sprache übersetzt, die sowohl der Manager als auch der Rust-Compiler verstehen.

\n\n

In diesem Artikel werden wir uns ansehen, wie man BDD in Rust in der Praxis implementiert. Sie erfahren, wie Sie Szenarien in menschlicher Sprache (Gherkin) schreiben, diese mit cucumber und specs automatisieren und warum dies Ihren Code nicht nur zuverlässig, sondern auch für das gesamte Team transparent macht. Kein überflüssiger Text – nur lebendiger Code und reale Beispiele.

\n\n

Was ist BDD und warum ist Rust dafür ideal?

\n\n

Behaviour-Driven Development ist eine Weiterentwicklung von TDD. Während TDD sich auf das „Wie teste ich Code?“ konzentriert, beantwortet BDD die Frage „Welches Verhalten wollen wir sehen?“. Sie schreiben Szenarien in der Sprache Gherkin (Given-When-Then), die gleichzeitig Tests und Dokumentation sind.

\n\n

Rust ist eine Sprache, die Strenge und Vorhersagbarkeit liebt. BDD in Rust bietet:

\n
    \n
  • Selbstdokumentierenden Code – jeder Entwickler liest das Szenario und versteht die Geschäftslogik.
  • \n
  • Sicherheit auf Typebene – der Compiler prüft, ob Ihre Schritte der Struktur entsprechen.
  • \n
  • Parallele Ausführung – BDD-Tests in Rust laufen dank async und Multithreading schnell.
  • \n
\n\n

Wann ist BDD in Rust besonders nützlich?

\n
    \n
  • API-Dienste mit klaren Verträgen (REST, GraphQL).
  • \n
  • Systeme mit Geschäftsregeln (Finanzen, Logistik, Spiele).
  • \n
  • Mikroservices, bei denen die Integration zwischen Komponenten wichtig ist.
  • \n
\n\n

Werkzeuge für BDD in Rust: Cucumber und Specs

\n\n

Das Rust-Ökosystem bietet zwei Hauptansätze:

\n\n

1. cucumber – das klassische BDD-Framework

\n

Ermöglicht das Schreiben von Szenarien in Gherkin (.feature-Dateien) und deren Verknüpfung mit Rust-Code. Unterstützt async, benutzerdefinierte Makros und Berichte.

\n\n

2. specs – eine leichte und schnelle Alternative

\n

Erfordert keine Gherkin-Dateien – Szenarien werden direkt in Rust mit Makros geschrieben. Ideal, wenn Sie keinen separaten Parser mitbringen möchten.

\n\n

Wir konzentrieren uns auf cucumber, da es maximale Flexibilität bietet und dem BDD-Standard entspricht.

\n\n

Unser erstes BDD-Szenario in Rust schreiben

\n\n

Lassen Sie uns einen einfachen Rabattrechner erstellen. Geschäftsregel: Wenn der Kaufbetrag mehr als 1000 Rubel beträgt, gibt es 10% Rabatt. Ansonsten 0%.

\n\n

Schritt 1: Abhängigkeiten installieren

\n

Fügen Sie in Cargo.toml hinzu:

\n
[dev-dependencies]\ncucumber = "0.20"\ntokio = { version = "1", features = ["full"] }\nasync-trait = "0.1"\n
\n\n

Schritt 2: Feature-Datei erstellen

\n

Datei tests/features/discount.feature:

\n
Feature: Rabattberechnung\n  Als ein Kunde\n  möchte ich einen Rabatt auf einen großen Einkauf erhalten\n  um Geld zu sparen\n\n  Szenario: Einkauf über 1000 Rubel\n    Gegeben sei der Kaufbetrag "1500"\n    Wenn ich die Rabattberechnung anfordere\n    Dann sollte der Rabattbetrag "150" sein\n\n  Szenario: Einkauf unter 1000 Rubel\n    Gegeben sei der Kaufbetrag "500"\n    Wenn ich die Rabattberechnung anfordere\n    Dann sollte der Rabattbetrag "0" sein\n
\n\n

Schritt 3: Schritte in Rust schreiben

\n

Erstellen Sie tests/steps/discount_steps.rs:

\n
use cucumber::{given, then, when, World};\nuse async_trait::async_trait;\n\n#[derive(Debug, Default)]\nstruct DiscountWorld {\n    purchase_amount: f64,\n    discount: f64,\n}\n\n#[async_trait(?Send)]\nimpl World for DiscountWorld {\n    // Leere Implementierung der Einfachheit halber\n    async fn new() -> Self {\n        Self::d                

Blogs

Buchempfehlungen