Test::BDD::Cucumber::Manual::Steps(3pm) User Contributed Perl Documentation Test::BDD::Cucumber::Manual::Steps(3pm)

Test::BDD::Cucumber::Manual::Steps - How to write Step Definitions

version 0.86

The 'code' part of a Cucumber test-suite are the Step Definition files which match steps, and execute code based on them. This document aims to give you a quick overview of those.

Most of your step files will want to start something like:

 #!perl
 package my_step_functions_for_feature_X;
 use strict;
 use warnings;
 use Test::More; # 'use Test2::V0;' is also supported
 use Test::BDD::Cucumber::StepFile;

The fake shebang line gives some hints to syntax highlighters, and "use strict;" and "use warnings;" are hopefully fairly standard at this point.

Most of my Step Definition files make use of Test::More, but you can use any Test2 or Test::Builder based testing module. E.g. "Test2::V0" or "Test::Exception".

Test::BDD::Cucumber::StepFile gives us the functions "Given()", "When()", "Then()" and "Step()".

 Given qr/I have (\d+)/, sub {
    S->{'count'} += $1;
 };
 When "The count is an integer", sub {
    S->{'count'} =
        int( S->{'count'} );
 };
 Then qr/The count should be (\d+)/, sub {
    is( S->{'count'}, C->matches->[0], "Count matches" );
 };

Each of the exported verb functions accept a regular expression (or a string that's used as one), and a coderef. The coderef is passed a single argument, the Test::BDD::Cucumber::StepContext object. Before the subref is executed, localized definitions of "S" and "C" are set, such that the lines below are equivalent:

  # Access the first match
  sub { my $context = shift; print $context->matches->[0] }
  sub { C->matches->[0] }
  # Set a value in the scenario-level stash
  sub { my $context = shift; my $stash = $context->stash->{'scenario'}; $stash->{'count'} = 1 }
  sub { S->{'count'} = 1 }

We will evaluate the regex immediately before we execute the coderef, so you can use $1, $2, $etc. Similarly you can access named matches using $+{match_name}.

Step functions have access to the various properties of the step, scenario and feature in which they're being used. This includes tags, line numbers, etc. E.g.:

  # Examples of step properties
  C->step->line->number
  C->step->verb
  C->step->original_verb
  # Examples of scenario properties
  C->scenario->name
  C->scenario->tags
  # Examples of feature properties
  C->feature->name
  C->feature->tags
  C->feature->language

For a full review of available properties, see Test::BDD::Cucumber::Model::Step, Test::BDD::Cucumber::Model::Scenario and Test::BDD::Cucumber::Model::Feature respectively.

Sometimes you want to call one step from another step. You can do this via the StepContext, using the "dispatch()" method. For example:

  Given qr/I have entered (\d+)/, sub {
        C->dispatch( 'Given', "I have pressed $1");
        C->dispatch( 'Given', "I have pressed enter", { some => 'data' } );
  };

For more on this topic, check the Redispatching section in the documentation for "Test::BDD::Cucumber::StepContext".

Both feature files and step files can be written using non-english Gherkin keywords. A german feature file could look like the example below.

  # language: de
  Funktionalität: Grundlegende Taschenrechnerfunktionen
    Um sicherzustellen, dass ich die Calculator-Klasse korrekt programmiert habe,
    möchte ich als Entwickler einige grundlegende Funktionen prüfen,
    damit ich beruhigt meine Calculator-Klasse verwenden kann.
    Szenario: Anzeige des ersten Tastendrucks
      Gegeben sei ein neues Objekt der Klasse Calculator
      Wenn ich 1 gedrückt habe
      Dann ist auf der Anzeige 1 zu sehen

To see which keywords (and sub names) to use, ask pherkin about a specific language:

 > pherkin --i18n de
 | feature          | "Funktionalität"                             |
 | background       | "Grundlage"                                  |
 ...
 | given (code)     | "Angenommen", "Gegebensei", "Gegebenseien"   |
 | when (code)      | "Wenn"                                       |
 | then (code)      | "Dann"                                       |

The last three lines of this list show you which sub names to use in your step file as indicated by the '(code)' suffix. A corresponding step file specifying a step function for "Wenn ich 1 gedrückt habe", could be:

  #!perl
  use strict;
  use warnings;
  use utf8;    # Interpret accented German chars in regexes and identifiers properly
  use Test::More;
  use Test::BDD::Cucumber::StepFile;
  Wenn qr/^ich (.+) gedrückt habe/, sub {
      S->{'Calculator'}->press($_) for split( /(,| und) /, C->matches->[0] );
  };

For more extensive examples see examples/i18n_de/ and examples/i18n_es.

Next to the steps that will be matched directly against feature file input, a number of additional step functions are supported:

When writing step files, it's a good idea to take a few things into account.

How step files are loaded is discussed in Test::BDD::Cucumber::Manual::Architecture, but isn't of much interest. Of far more interest should be seeing what you have available in Test::BDD::Cucumber::StepContext...

Peter Sergeant "pete@clueball.com"

  Copyright 2019-2023, Erik Huelsmann
  Copyright 2011-2019, Peter Sergeant; Licensed under the same terms as Perl
2023-08-29 perl v5.36.0