cucumber-rust

Documentation Actions Status

An implementation of the Cucumber testing framework for Rust. Fully native, no external test runners or dependencies.

The 0.6.x macro has been removed. If you need to use this macro, please continue to use the 0.6 version.

Usage

Create a directory called tests/ in your project root and create a test target of your choice. In this example we will name it cucumber.rs.

Add this to your Cargo.toml:

```toml [[test]] name = "cucumber" harness = false # Allows Cucumber to print output instead of libtest

[dev-dependencies] cucumber = { package = "cucumber_rust", version = "^0.7.0" } ```

Create a directory called features/ and put a feature file in it named something like example.feature. It might look like:

```gherkin Feature: Example feature

Scenario: An example scenario Given I am trying out Cucumber When I consider what I am doing Then I am interested in ATDD And we can implement rules with regex

```

And here's an example of implementing those steps using our tests/cucumber.rs file:

```rust extern crate cucumberrust as cucumber; use asynctrait::async_trait; use std::{convert::Infallible, cell::RefCell};

pub struct MyWorld { // You can use this struct for mutable context in scenarios. foo: String, bar: usize, some_value: RefCell, }

impl MyWorld { async fn testasyncfn(&mut self) { *self.somevalue.borrowmut() = 123u8; self.bar = 123; } }

[async_trait(?Send)]

impl cucumber::World for MyWorld { type Error = Infallible;

async fn new() -> Result<Self, Infallible> {
    Ok(Self {
        foo: "wat".into(),
        bar: 0,
        some_value: RefCell::new(0),
    })
}

}

mod example_steps { use cucumber::{Steps, t};

pub fn steps() -> Steps<crate::MyWorld> {
    let mut builder: Steps<crate::MyWorld> = Steps::new();

    builder
        .given_async(
            "a thing",
            t!(|mut world, _step| {
                world.foo = "elho".into();
                world.test_async_fn().await;
                world
            })
        )
        .when_regex_async(
            "something goes (.*)",
            t!(|world, _matches, _step| world),
        )
        .given(
            "I am trying out Cucumber",
            |mut world: crate::MyWorld, _step| {
                world.foo = "Some string".to_string();
                world
            },
        )
        .when("I consider what I am doing", |mut world, _step| {
            let new_string = format!("{}.", &world.foo);
            world.foo = new_string;
            world
        })
        .then("I am interested in ATDD", |world, _step| {
            assert_eq!(world.foo, "Some string.");
            world
        })
        .then_regex(
            r"^we can (.*) rules with regex$",
            |world, matches, _step| {
                // And access them as an array
                assert_eq!(matches[1], "implement");
                world
            },
        );

    builder
}

}

fn main() { // Do any setup you need to do before running the Cucumber runner. // e.g. setupsomedb_thing()?;

let runner = cucumber::Cucumber::<MyWorld>::new()
    .features(&["./features"])
    .steps(example_steps::steps());

// You may choose any executor you like (Tokio, async-std, etc)
// You may even have an async main, it doesn't matter. The point is that
// Cucumber is composable. :)
futures::executor::block_on(runner.run());

} ```

The full gamut of Cucumber's Gherkin language is implemented by the gherkin-rust project. Most features of the Gherkin language are parsed already and accessible via the relevant structs.

License

This project is licensed under either of

at your option.