How Cucumber Works

Each test case in Cucumber is called a scenario, and scenarios are grouped into features. Each scenario contains several steps. These feature files must follow some basic syntax rules named Gherkin. Gherkin files are plain text and have a .feature extension.

 

Browser automation library Capybara

 

Advantages of Using Cucumber

  • Can write your specifications in more than forty different spoken languages.
  • Can use tags to organize and group your scenarios

 

As soon as Cucumber encounters a failed or pending step, it will stop running the scenario and skip the remaining steps.

 

Command-line argument ARGV[0]

 

Gherkin Basics

Keywords:

Feature

Background

Scenario

Given

When

Examples

Then

And

But

*

Scenario Outline

 

 

  • Cucumber test.feature --dry-run
 The --dry-run switch tells Cucumber to parse the file without executing it. It will tell you if your Gherkin isn't valid.

 

Feature

Each Gherkin file begins with the Feature keyword. This keyword doesn't really affect the behavior of your Cucumber tests at all; it just gives you a convenient place to put some summary documentation about the group of tests that follow.

 

The text immediately following on the same line as the Feature keyword is the name of the feature, and the remaining lines are its description. You can include any text you like in the description except a line beginning with one of the words Scenario, Background, or Scenario Outline. The description can span multiple lines.

 

In valid Gherkin, a Feature must be followed by one of the following:

  • Scenario
  • Background
  • Scenario Outline

 

Scenario

Each scenario tells a little story describing something that the system should be able to do.

 

Given, When, Then

We use Given to set up the context where the scenario happens, When to interact with the system somehow, and Then to check that the outcome of that interaction was what we expected.

 

Feature Injection Template

In order to <meet some goal>

As a <type of stakeholder>

I want <a feature>

 

And, But

 

Replacing Given/When/Then with Bullets

There's  an additional keyword you can use to start a step: * (an asterisk)

 

Stateless

Each scenario must take sense and be able to be executed independently of any other scenario.

 

Comments

Like in Ruby, comments start with a # character. Unlike in Ruby, comments have to be the first and only thing on a line (apart from whitespace).

 

Spoken languages

Putting a # language: comment on the first line of a feature file tells Cucumber which spoken language that feature is written in. If you omit this header, Cucumber will default to English.

Cucumber --i18n help

List all valid languages

A project can have a mix of features that use different spoken languages. However, all the scenarios in a feature have to use the same spoken language.

 

Any $ sign——including any letter or number following it,will be interpreted as an argument.

 

Creating a Step Definition

Step definitions live in regular Ruby files in the features/step_definitions folder. Step definitions use regular expressions to declare the steps that they can handle. Because regular expressions can contain wildcards, one step definition can handle serval different steps.

 

Given, When, Then Are the Same

It doesn't actually matter which of the three methods you use to register a step definition. Under the hood, all of the keyword methods are aliases for Cucumber::RbDsl#register_rb_step_definition.

 

Wildcard

Alternation

Given /I have deposited \$(100|200) in my Account/ do |amount|

The Dot

Given /I have deposited \$(…) in my Account/ do |amount|

## A dot means match any single character.

The Plus Modifier

Given /I have deposited \$(.*) in my Account/ do |amount|

## The star modifier means any number of times.

Given /I have deposited \$(\d+) in my Account/ do |amount|

## The + modifier means at least once

## The question mark modifier means zero or one times.

Character Classes

Given /I have deposited \$([0123456789]*)\ in my Account/ do |amount|

Given /I have deposited \$([0-9]*)\ in my Account/ do |amount|

## Character classes allow you to tell the regular expression to match one of a range of characters.

Shorthand Character Classes

Given /I have deposited \$(\d*)\ in my Account/ do |amount|

## use \d as a shorthand for [0-9]

 

 

 

Multiple Parameters

Given /I have deposited \$(\d+) in my (\w+) Account/ do |amount, account_type|

 

The Question Mark Modifier

  1. Means zero or one times
  2. Makes the preceding character optional
 

Given /I have (\d+) cucumbers? in my basket/ do |number|

Match:

  1. Given I have 1 cucumber in my basket
  2. Given I have 20 cucumbers in my basket     

 

Noncapturing Groups

When /I (?:visit|go to) the homepage/ do

Match:

When I visit the homepage

When I go to the homepage

The ?: at the start of the group marks it as noncapturing, meaning Cucumber won't pass it as an argument to our block.

 

Anchors

The step definition snippets that Cucumber prints for undefined steps start with a ^ and end with a $.

These two metacharacters are called anchors, because they're used to tie down each end of the regular expression to the beginning and end of the string that they match on.

 

Returning Results

In Cucumber, a scenario that's been executed can end up in any of the following states:

  • Undefined (in yellow)

When Cucumber can't find a step definition that matches a step, it marks the step as undefined (yellow) and steps the scenario. The rest of the steps in the scenario will be either skipped or marked as undefined too if they don't have a matching step definition themselves.

  •  Pending (in yellow)

When you call pending from within a step definition. It raises a Cucumber::Pending error. You can use the pending status as a temporary signpost to your teammates that you're in the middle of working on something.

Given /^I have deposited \$(\d+) in my account$/ do |amount|

  • Failed (in red)
    If the block of code executed by a step definition raises an exception. Cucumber will mark that step as failed and stop the scenario. The rest of the steps in the scenario will be skipped.
  •  Passed

 

Strict Mode

--strict command-line option

Cucumber will return an exit code of 1 (to indicate an error) if there are any undefined or pending steps.

 

Assertion

An assertion is a check in your tests that describes some condition that you expect to be satisfied.

 

Assertion Library

The main assertion libraries: Rspec, MiniTest, and Wrong.

# MiniTest

>> require 'test/unit'

>> include Test::Unit::Assertions

>> assert_equal 'green', 'cucumber'

MiniTest::Assertion: <"green"> expected but was <"cucumber">

# RSpec

>> require 'respec/expectations'

>> "green".should == "cucumber"

>> my_account.balance.should eq(amount.to_i)

>> Rspec::Expectations::ExceptationNotMetError: expected: "cucumber"

                got: "green" (using ==)

# Wrong

>> require 'wrong'

>> include Wrong

>> assert { 'green' == 'cucumber'}

Wrong::Assert::AssertionFailedError: Expected ("green" == "cucumber"), but String differ at position 0:

   first: "green"

   second: "cucumber"

MiniTest's assertions are built into Ruby

RSpec's assertions are automatically loaded  by Cucumber.

 

 

Background

A background section in a feature file allows you to specify a set of steps that are common to every scenario in the file.

At runtime, the steps in the background are executed at the beginning of each scenario. You can have a single Background element per feature file, and it must appear before any of the Scenario or Scenario Outline elements. You can give it a name, and you have space to put a multiline description before the first step.

Background:  Change PIN

    Given I have been issued a new card

    And I insert the card, entering the correct PIN

    And I choose "Change PIN" from the menu

 

Scenario:  Change PIN successfully

   When I change the PIN to 9574

   Then the system should remember my PIN is now 9574

 

Scenario: Try to change PIN to the same as before

   When I try to change the PIN to the original PIN number

   Then I should see a warning message

   And the system should not have changed my PIN

 

Data Tables (Cucumber::Ast::Table)

Data tables give you a way to extend a Gherkin step beyond a single line to include a larger piece of data.

Given a User "Michael Jackson" born on August 29, 1958

And a User "Elvis" born on January 8, 1935

And a User "John Lennon" born on October 9, 1940

Given these users:

| name                    | date of birth       |

| Michael Jackson | August 29, 1958 |

| Elvis                      | January 8, 1935  |

| John Lennon       | October 9, 1940  |

The table starts on the line immediately following the step, and its cells are separated using the pipe character:|. You can line up the pipes using whitespace to make the table look tidy. Cucumber will strip out the values in each cell, ignoring the surrounding whitespace.

Can use a heading for each column / row, or just specify a list.

Tweak the comparison behavior by passing a hash of options to diff!.

 

Scenario Outline

When having several scenarios that follow exactly the same pattern of steps, just with different input values or expected outcomes.

Feature: Withdraw Fixed Amount

  

      The "Withdraw Cash" menu contains several fixed amounts to speed up transactions for user.

 

      Scenario Outline: Withdraw fixed amount

             Given I have <Balance> in my account

             When I choose to withdraw the fixed amount of <Withdrawal>

             Then I should receive <Received> cash

             And the balance of my account should be <Remaining>

 

     Examples: Successful withdrawl

         The amount is valid (lower than the balance)  

            | Balance   |   Withdrawal   |   Received   |   Remaining   |

            | $500        |   $50                  |   $50            |   $450             |    

            | $500        |   $100                |   $100         |   $400             |  

 

Indicate placeholders within the scenario outline using angle brackets (<…>) where we want real values to be substituted.

The scenario outline itself is useless without a table of Examples.

You can have any number of Scenario Outline elements in a feature and any number of Examples tables under each scenario outline.

$ cucumber  --expand

--expand option will print each example in a scenario outline as though it were a scenario.

 

Difference of Data tables  & Scenario outline

Data tables just describe a lump of data to attach to a single step of a single scenario. In a scenario outline, each row of an Examples table represents a whole scenario to be executed by Cucumber. In fact, you might want to use the keyword Scenarios in place of Examples if you find that more readable.

 

 Nesting Steps

The %{…} construct is a way to tell Ruby that you have a string going across multiple lines.

Given /^an activated customer (\w+) exists $/    do |name|

   steps  %{

         Given I create a customer with login #{name}

         And I register the customer with login #{name}

   }

end

The only time this won't work is if the argument you're passing is a data table. In that case you can use another method, step to call a specific step, passing the actual typed DataTable object as an argument.

Given /^a (\w+) widget with the following details: $/  do |color, details_table|

    step "I create a #{color} widget with the following details:", details_table

    step  %{

           And I register the #{color} widget

           And I activate the #{color} widget

}

 end

 

Doc Strings

Doc strings allow you to specify a larger piece of text than you could fit on a single line.

the """ triple quotes

The indentation inside the triple quotes will be eliminated.

Doc strings

Remain indentation within your string