Data tables represent a handy way for passing a list of values to a step definition (and so, to a step matching function). This is a vital ability for writing table driven tests.
Feature: Animal feature
Scenario: If we feed a hungry animal it will no longer be hungry
Given a hungry animal
| animal |
| cat |
| dog |
| 🦀 |
When I feed the animal multiple times
| animal | times |
| cat | 2 |
| dog | 3 |
| 🦀 | 4 |
Then the animal is not hungry
Data, declared in the table, may be accessed via Step argument:
externcrate cucumber;
externcrate tokio;
use std::collections::HashMap;
use cucumber::{World, gherkin::Step, given, then, when};
#[given(regex = r"^a (hungry|satiated) animal$")]asyncfnhungry_animal(world: &mut AnimalWorld, step: &Step, state: String) {
let state = match state.as_str() {
"hungry" => true,
"satiated" => false,
_ => unreachable!(),
};
ifletSome(table) = step.table.as_ref() {
for row in table.rows.iter().skip(1) { // NOTE: skip headerlet animal = &row[0];
world
.animals
.entry(animal.clone())
.or_insert(Animal::default())
.hungry = state;
}
}
}
#[when("I feed the animal multiple times")]asyncfnfeed_animal(world: &mut AnimalWorld, step: &Step) {
ifletSome(table) = step.table.as_ref() {
for row in table.rows.iter().skip(1) { // NOTE: skip headerlet animal = &row[0];
let times = row[1].parse::<usize>().unwrap();
for _ in0..times {
world.animals.get_mut(animal).map(Animal::feed);
}
}
}
}
#[then("the animal is not hungry")]asyncfnanimal_is_fed(world: &mut AnimalWorld) {
for animal in world.animals.values() {
assert!(!animal.hungry);
}
}
#[derive(Debug, Default)]structAnimal {
pub hungry: bool,
}
impl Animal {
fnfeed(&mutself) {
self.hungry = false;
}
}
#[derive(Debug, Default, World)]pubstructAnimalWorld {
animals: HashMap<String, Animal>,
}
#[tokio::main]asyncfnmain() {
AnimalWorld::run("tests/features/book/writing/data_tables.feature").await;
}
NOTE: The whole table data is processed during a single step run.