Tags

Tags represent meta information of scenarios and features.

They can be used for different purposes, but in the majority of cases it's just:

  • either running a subset of scenarios filtering by tag;
  • or making scenario run in isolation via @serial tag;
  • or allowing scenarios to be skipped with @allow.skipped tag.

Filtering

A scenario may have as many tags as it requires (they should be separated with spaces):

Feature: Animal feature

  @hungry
  Scenario: If we feed a hungry cat it will no longer be hungry
    Given a hungry cat
    When I feed the cat
    Then the cat is not hungry

  @satiated @second
  Scenario: If we feed a satiated cat it will not become hungry
    Given a satiated cat
    When I feed the cat
    Then the cat is not hungry

To filter out running scenarios we may use:

record

Inheritance

Tags may be placed above the following Gherkin elements:

It's not possible to place tags above Background or steps (Given, When, Then, And and But).

Tags are inherited by child elements:

@feature
Feature: Animal feature

  @scenario
  Scenario Outline: If we feed a hungry animal it will no longer be hungry
    Given a hungry <animal>
    When I feed the <animal> <n> times
    Then the <animal> is not hungry

  @home
  Examples: 
    | animal | n |
    | cat    | 2 |
    | dog    | 3 |

  @dire
  Examples: 
    | animal | n |
    | lion   | 1 |
    | wolf   | 1 |

NOTE: In Scenario Outline it's possible to use tags on different Examples.

record

Isolated execution

cucumber crate provides out-of-the-box support for @serial tag. Any scenario marked with @serial tag will be executed in isolation, ensuring that there are no other scenarios running concurrently at the moment.

Feature: Animal feature
    
  Scenario: If we feed a hungry cat it will no longer be hungry
    Given a hungry cat
    When I feed the cat
    Then the cat is not hungry

  @serial
  Scenario: If we feed a satiated cat it will not become hungry
    Given a satiated cat
    When I feed the cat
    Then the cat is not hungry

NOTE: @serial tag may also be used for filtering as a regular one.

record

TIP: To run the whole test suite serially, consider using --concurrency=1 CLI option, rather than marking evey single feature with a @serial tag.

Failing on skipped steps

As a test suit grows, it may become harder to notice how minimal changes to regular expressions can lead to mismatched steps.

Using Cucumber::fail_on_skipped() method fails the whole test suite if some steps miss the implementation, so ensures that the whole test suite is covered.

Feature: Animal feature
    
  Scenario: If we feed a hungry cat it will no longer be hungry
    Given a hungry cat
    When I feed the cat
    Then the cat is not hungry

  Scenario: If we feed a satiated cat it will not become hungry
    Given a wild cat
    When I feed the cat
    Then the cat is not hungry
extern crate cucumber;
extern crate tokio;

use std::time::Duration;

use cucumber::{given, then, when, World};
use tokio::time::sleep;

#[derive(Debug, Default)]
struct Animal {
    pub hungry: bool,
}

impl Animal {
    fn feed(&mut self) {
        self.hungry = false;
    }
}

#[derive(Debug, Default, World)]
pub struct AnimalWorld {
    cat: Animal,
}

#[given(regex = r"^a (hungry|satiated) cat$")]
async fn hungry_cat(world: &mut AnimalWorld, state: String) {
    sleep(Duration::from_secs(2)).await;

    match state.as_str() {
        "hungry" => world.cat.hungry = true,
        "satiated" => world.cat.hungry = false,
        _ => unreachable!(),
    }
}

#[when("I feed the cat")]
async fn feed_cat(world: &mut AnimalWorld) {
    sleep(Duration::from_secs(2)).await;

    world.cat.feed();
}

#[then("the cat is not hungry")]
async fn cat_is_fed(world: &mut AnimalWorld) {
    sleep(Duration::from_secs(2)).await;

    assert!(!world.cat.hungry);
}

#[tokio::main]
async fn main() {
    AnimalWorld::cucumber()
        .fail_on_skipped()
        .run_and_exit("tests/features/book/writing/tags_skip_failed.feature")
        .await;
}

TIP: Using @allow.skipped tag allows scenarios being skipped even in Cucumber::fail_on_skipped() mode. Use the one to intentionally skip the implementation.

Feature: Animal feature
    
  Scenario: If we feed a hungry cat it will no longer be hungry
    Given a hungry cat
    When I feed the cat
    Then the cat is not hungry

  @allow.skipped
  Scenario: If we feed a satiated cat it will not become hungry
    Given a wild cat
    When I feed the cat
    Then the cat is not hungry

record

NOTE: @allow.skipped tag may also be used for filtering as a regular one.

record