Book Image

Instant Cucumber BDD How-to

By : Wayne Ye
Book Image

Instant Cucumber BDD How-to

By: Wayne Ye

Overview of this book

<p>Cucumber is a Behavior Driven Design framework, which allows a developer to write specification tests which then tests that the program works as it should. It is a different development paradigm, as it involves writing what the program should do first, then you develop until it passes the tests.<br /><br />Instant Cucumber BDD How-to will cover basics of Cucumber in a Behaviour Driven Development (BDD) style and explain the essence of Cucumber, describe how to write Cucumber features to drive development in a real project, and also describe many pro tips for writing good Cucumber features and steps. Cucumber is a very fun and cool tool for writing automated acceptance tests to support software development in a Behaviour Driven Development (BDD) style.<br /><br />Instant Cucumber BDD How-to will highlight Cucumber's central role in a development approach called Behaviour Driven Development (BDD), describe how to write Cucumber features to drive development in a real project, and finally introduce some famous third-party libraries used inline with Cucumber.</p> <p>It will show you how to carry out all the tasks associated with BDD using Cucumber and write basic Cucumber steps. It will assist you in using Pro tips for writing expressive Gherkin and implement guidelines for writing DRY steps. You'll learn how to use Cucumber's Gherkin to describe the behavior customers want from the system in a plain language.</p>
Table of Contents (7 chapters)

Mastering pro tips for writing expressive Gherkin (Intermediate)


In the Building a real web application with Cucumber (Intermediate) recipe, we completed five simple user stories driven by Cucumber, and we learnt how to drive a Rails web application development using Cucumber in a BDD style.

Gherkin provides various kinds of expressive syntax. In this recipe, we are going to learn various kinds of skills and tips with Cucumber Gherkin DSL, and how to write readable, organized, and reusable Gherkin to help us solve real-world problems.

Getting ready

We will reuse the Rails application, cucumber_bdd_how_to, which we created in the Writing your first Hello World feature (Simple) recipe, so please cd into that directory to get prepared.

How to do it...

In the following sections, a number of useful Gherkin tips are introduced and covered exhaustively.

Define a background for scenarios

  1. When we write Cucumber tests, we usually encounter this situation: a number of scenarios rely on the same step(s). For example, as a registered developer on GitHub, I can manage my profile, my repositories, or my SSH keys, then our feature can be written as follows:

    Feature: Github account management
    In order to manage my profile, repositories and my SSH Keys
    As a registered developer
    I Should be able to log into system and manage my account
     Scenario: Change my avatar
       Given I logged into Github with account "Wayne Ye"
       When I click my avatar to go to the "Your Profile" page
       Then I can change my avatar with "Wayne.png"
    
     Scenario: View my repositories
       Given I logged into Github with account "Wayne Ye"
       When I click my avatar to go to the "Your Profile" page
       And I click on "Repositories" hyperlink
       Then I should be able to see all my repositories
    
     Scenario: Add a SSH KeyGiven I logged into Github with account "Wayne Ye"
       When I click my avatar to go to the "Your Profile" page
       And I click on "SSH Keys" hyperlink
       Then I add a new SSH key
  2. You will notice that all the scenarios require you to log into GitHub, and in more complex cases the share steps can be more. This could be quite tedious, so in this situation we can use Background:

    Feature: Github account management
    In order to manage my profile, repositories and my SSH Keys
    As a registered developerI Should be able to log into system and manage my account
    
     Background:
       Given I logged into Github with account "Wayne Ye"
       When I click my avatar goto the "Your Profile" page
    
     Scenario: Change my avatar
       Then I can change my avatar with "Wayne.png"
    
     Scenario: View my repositories
       And I click on "Repositories" hyperlink
       Then I should be able to see all my repositories
    
     Scenario: Add a SSH Key
       And I click on "SSH Keys" hyperlink
       Then I add a new SSH key

Whenever possible, use Gherkin Background to centralize the scenario shared steps, be DRY (don't repeat yourself), and get better maintainability!

Outline-related attributes in a table

  1. Sometimes we need to describe the data in steps. When the data is in pieces, our step could be verbose, for example, a user registration feature:

    Feature: User registration
    In order to shop in ABC online shop
    As a userI should be able to register an account through registration page
    
     Scenario: register with valid information
       When I am on the registration page of ABC online shop
       And I fill the "Full Name" form with "Wayne Ye"
       And I fill the "Address" form with "123 Main Street"
       And I fill the "Email" form with "[email protected]"
       And I fill the "Password" form with "asdf"
       Then I should be redirected to registration success page
  2. Luckily, Gherkin provides a data table to deal with these kinds of scenarios. The data table gives you a way to extend a Gherkin step beyond a single line to include a larger piece of data. The preceding example can be easily and gracefully described as follows:

    Feature: User registration
    In order to shop in ABC online shop
    As a userI should be able to register an account through registration page
    
     Scenario: register with valid information
       When I am on the registration page of ABC online shop
       And I fill the form with the following value
         | Full Name| Address     | Email          | Password |
         | Wayne Ye | No 12 Pt Street| [email protected] |asdf|
       Then I should be redirected to registration success page
  3. Much greater readability and maintainability! The preceding data table contains column headers to specify each field, and sometimes it can also be used without headers, for example, when it represents a list of data.

    Scenario: instance messenger online 
     When I log into ABC social website
     And I open up the IM tab
     Then I should see my online friends
       | Mark   |
       | Sean   |
       | Shelly |
       | Wendy  |

Using a scenario outline

  1. Consider a number of scenarios. They require similar steps as a part of them; the difference is different input values. Typically, a registration validation scenario is a good example:

    Background:
     When I am on the registration page
    
    Scenario: user registration
     When I fill "email" field with ""
     And I press "Register" button
     Then I should see error message "Email cannot be blank"
     When I fill "email" field with "wayne"
     And I press "Register" button
     Then I should see error message "Please input valid Email address"
     And I fill "password" field with ""
     And I press "Register" button
     Then I should see error message "Password cannot be blank"
     And I fill "password" field with "asdf"
     And I press "Register" button
     Then I should see error message "Password is too short"
  2. Ouch! A registration in the real world is definitely more complex than this one! The preceding scenario looks so ugly; the right way is to adopt Gherkin's Scenario Outline:

    Scenario Outline: user registration
     When I fill "<field_name>" field with "<value>"
     And I press "Register" button
     Then I should see error message "<error_message>"
    
    Examples:
     |field_name| value     | error_message          |
     | Email    |           | Email cannot be blank  |
     | Email    | wayne     | Please input valid Email address |
     | Email    |[email protected]| Email has already been taken     |
     | Password |          | Password cannot be blank     |
     | Password | asdf     | Password is too short        |

By utilizing Scenario Outline, the feature looks clean and easy, and it refrains from writing duplicate steps. Additionally, we can quickly find out missed cases because of its tidy text. For example, in the previous case, we can easily point out that we lack the maximum length check for both the e-mail and password.

Doc strings

  1. Sometimes we have a string with a new line in the step; in this scenario we can use Gherkin Dot Strings to represent the long string. Typically a step with account activation e-mail content is as follows:

    Scenario: User registration
     When the user clicks "Register"
     Then an Email should be sent out with content:
    """
    Dear customer,
    Thank you for registering at ABC website!
    Please click the following link to activate your account!
    http://foo-web.com/user/wayne/activation
    """
  2. In the implementation step, the string content will be passed in as Cucumber::Ast::Docstring:

    Then /^an Email should be sent out with content:$/ do |string|p string.class # Cucumber::Ast::DocString
     p string
     # "Dear customer,\nThank you for registering at ABC website!\nPlease click the following link to activate your account!\nhttp://foo-web.com/user/wayne/activation"
    end

There's more…

There are two extra tips for organizing Cucumber features and writing better features.

Using tags

Gherkin allows you to add meaningful tags, for example:

  • Mark important, minimum marketable features as @important or @MMV

  • Mark features that require logging into the system as @require_login

  • Mark work in progress features as @todo or @wip

Tag(s) can be applied to features or scenarios; scenarios, scenario outlines, or examples will inherit any tags that exist on the containing feature.

Tag(s) are pretty useful and provide many benefits. For example, they can help in organizing and filtering features:

  • We can specify Cucumber to run all features marked as @mandatory:

    $ cucumber --tags @mandatory
    
  • We can specify Cucumber to run all features except @todo ones:

    $ cucumber --tags ~@todo
    
  • We can specify Cucumber to run all @finished and @integration features:

    $ cucumber --tags @finished --tags @integration
    
  • We can specify Cucumber to run features with a maximum number limit. The preceding command demonstrates both the ORing tags and the tag limits:

    $ cucumber --tags @dev:4,@qa:6
    

Cucumber will fail if there are more than four @dev features or more than six @qa features, even if all the features passed. This tip will be pretty useful in the Kanban development methodology (a scheduling system invented by Toyota for the Lean and Just-in-Time productions) because we want to limit the number of Working in Progress features.

Apply tag logic by using hooks. We can add a block of Ruby code before/around/after a specific tag. This is massively useful, for example, because we can implement login logic before all features/scenarios marked with a @require_login tag:

Before('@require_login') do
 # Put login logic here
end
After('@require_login') do
 # Perform logout logic
end

When we run the @require_login tag, the login logic hook will be executed automatically. Here it just demonstrates the tagged hooks. There are also scenario hooks, step hooks, and global hooks.

Imperative steps versus declarative steps

Do you remember in the beginning of the previous recipe, we wrote a Gherkin feature for the first story:

Feature: Write blog
As a blog owner 
I can write new blog post
 Scenario: Write blog
   Given I am on the blog homepage
   When I click "New Post" link
   And I fill "My first blog" as Title
   And I fill "Test content" as content
   And I click "Post" button
   Then I should see the blog I just posted

Every step in this feature is granular; it describes each action used. Steps like these are called imperative steps (or communicative); as a comparison, another pattern of writing Gherkin is declarative (or informative), which suggests describing the user story over recording the user's actions.

For example, writing the previous feature in the declarative style will be as follows:

Feature: Write blog
As a blog owner 
I can write new blog post

 Scenario: Write blog
   Given I am on the blog homepage
   When I write a new blog post
   Then I should see the blog I just posted

A declarative step usually hides more details and provides better readability for business people. Many people prefer declarative steps over imperative steps since imperative steps could be brittle because they are usually tightly coupled with UI or a serial of business logic, whereas both of them could be changed as per the requirement.

Note

In the older version of Cucumber, there used to be a web_steps.rb generated under the step_definitions directory every time Cucumber got installed. However, to avoid people writing imperative steps, Aslak Hellesøy (the co-author of Cucumber) removed it. His original statement is as follows:

"The reason behind this is that the steps defined in web_steps.rb leads people to write scenarios of a very imperative nature that are hard to read and hard to maintain. Cucumber scenarios should not be a series of steps that describe what a user clicks. Instead, they should express what a user does."

However, an imperative step is not always bad. Using imperative steps in some cases is more appropriate and natural than declarative steps. It is usually simple to read and understand, so the suggestion here is trying to write declarative steps but using imperative steps whenever the need arises.