technical writing about behaviour driven test (BDD) using Cucumber

This is a tutorial / technical writing about behaviour driven test (BDD) using Cucumber (Gherkin)


Installing Cucumber -
This plugin is required for creating feature file/ BDD editor


Cucumber JVM JUnit
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.4</version>
</dependency>


Cucumber JVM Java
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.4</version>
</dependency>

Cucumber Core
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>1.2.4</version>
</dependency>


BDD - Behaviour Driven Development/ TDD.
The main purpose of BDD is to bridge the gap between the one who is developing the software by actually writing the code and the one who has the idea to have a software which does xyz things. 

Using cucumber we write test since the beginning of the project and can have an idea of actually how the software would behave when fully developed in a sense cucumber helps to develop a full set of automated acceptance test.


The main layer of cucumber test suite consists of Feature, Step Definition and Runner class.
The Feature file is where we actually write the test in plain English using a certain set of key words like Give/ When/ Then / And . But these keywords are just for illustration purpose, even if you use any hing arbitrary things would still work without any issue. 











Cucumber Feature Files

# Feature file containing scenarios of wordpress login
Feature: wordpress blog site login

Scenario: perform a successful login with valid credentials
Given I am on wordpress login page
When I enter valid userName and valid password
And I click on the login button
Then I am able to login to the wordpress

Scenario: perform a login with invalid userName
Given I am on wordpress login page
When I enter invalid userName and valid password
And I click on the login button
Then I should get ERROR: Invalid username.

Scenario: perform a login with invalid password
Given I am on wordpress login page
When I enter valid userName and in valid password
And I click on the login button
Then I should get ERROR: The password you entered for the email address subhra.s.das@gmail.com is incorrect.

Scenario: perform a login with invalid userName and invalid password
Given I am on wordpress login page
When I enter invalid userName and invalid password
And I click on the login button
Then I should get ERROR: Invalid email address


# Wordpress logout feature
Feature: wordpress logout feature

Scenario: to check for available links on logout option
Given I am on wordpress dashboard page
When I mouse hover to the logged in email address
Then I get the logged in email address
And Edit My Profile link
And Logout Option

Scenario: to validate a logout action
Given I am on wordpress dashboard page
When I mouse hover to the logged in email address
Then I get logout Option
And when i click on logut
Then i am logged out
And can see message You are now logged out on home page

Scenario: to check if sessions get invalidate after logout
Given I have performed a successful login
When I enter URL http://localhost:8888/wordpress/wp-admin/ directly in browser
And Hit enter
Then I should be redirected back to home page asking for userName and password


Cucumber Runner Class

The most import annotation used in the runner class is @CucumberOptions
Following options are available in cucumber



  • Features: path of the feature file or features file in format {"feature_file1","feature_file2"}
  • dryRun: by default the value is false. When it is true on those steps on feature file are executed whose steps are converted into step definition. For those in feature file whose steps are not converted as methods ins step definition file are skipped

When dryRun=false every steps in the feature files would be skipped if steps does not have a complete method in step definition class

when dryRun = true

when dryRun = false





  • glue: package name where the stepDefinition class resided
  • monochrome: for formatting 

In valid Gherkin a Feature must be followed by either

  • Scenario
  • Background
  • Scenario Outline 

Scenario: starts with description followed by steps which consists of keyword like Given, When, Then, And, But or you can simply ignore these keywords and write test steps using * .

Example
  Scenario: perform a successful login with valid credentials
    Given I am on wordpress login page
    When I enter valid userName and valid password
    And I click on the login button
    Then I am able to login to the wordpress


Background: 
When we have repeated steps in every scenario we can take those repeated steps in background

For Example : In this feature file several steps are repeated for every scenario. Instead of repeating this step on each scenario we can take this step on Background section as shown below:


# Feature file for creating new post and editing existing post and moving post to trash
Feature: wordpress post functionality of adding post, editing post and deleting post

Scenario: to validate add post functionality
Given i am on wordpress login page
When i enter valid userName and password
And click on login
Then i login to wordpress successfully
And i click on post

And click on add new
And i add post tilte and post body
Then i click on publish to publish a new post

Scenario: to validate edit post functionality
Given i am on wordpress login page
When i enter valid userName and password
And click on login
Then i login to wordpress successfully
And i click on post

And i select the post which i need to edit
And i click on edit
And enter updated details to the post
Then i click on update to update and publish the post at the same time

Scenario: to validate delete post functionality
Given i am on wordpress login page
When i enter valid userName and password
And click on login
Then i login to wordpress successfully
And i click on post
And i select the post
which i need to delete
And i select move to trash from dropdown
And click on apply

Modified the above feature file using Background
The steps in the background are executed at the beginning of each scenario, just as they were before. What we have done is made each individual scenario much easier to read. 
'

# Feature file for creating new post and editing existing post and moving post to trash
Feature: wordpress post functionality of adding post, editing post and deleting post

Backround: description of background section
Given i am on wordpress login page
When i enter valid userName and password
And click on login
Then i login to wordpress successfully
And i click on post

Scenario: to validate add post functionality
And click on add new
And i add post tilte and post body
Then i click on publish to publish a new post

Scenario: to validate edit post functionality
And i select the post which i need to edit
And i click on edit
And enter updated details to the post
Then i click on update to update and publish the post at the same time

Scenario: to validate delete post functionality
And i select the post which i need to delete
And i select move to trash from dropdown
And click on apply


DataDriven Test Using Cucumber

Given example for two scenario
Scenario 1: from list and
Scenario 2: from data table

Scenario: from list
Given the following users: user1,user2,user3,user4

Scenario: from data table
Given i have the following user and password
| userName | password |
| user_01 | password_01 |
| user_02 | password_01 |
| user_03 | password_01 |

This step definition is for the Feature -> scenario : from list

@Given("^the following users: (.*)")
public void the_following_users_user_user_user_user(List<String> userList) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// throw new PendingException();
Iterator<String> it = userList.iterator();
while (it.hasNext()) {
System.out.println(it.next());

}
}


This step definition is for Feature "From data table"
Step Definition method for data table using Map<String, String>


 @Given("^i have the following user and password$") public void  dataMap01(Map<String, String> userDetails) throws Throwable { // Write
// code here that turns the phrase above into concrete actions // For
// automatic transformation, change DataTable to one of // List<YourType>,
// List<List<E>>, List<Map<K,V>> or Map<K,V>. // E,K,V must be a scalar
// (String, Integer, Date, enum etc) // throw new PendingException();
Set<Entry<String, String>> set = userDetails.entrySet();
Iterator<Entry<String, String>> it = set.iterator(); while(it.hasNext())
{ Entry<String, String> next = it.next();
System.out.println(next.getKey()); System.out.println(next.getValue()); }

}


Step Definition method for data table using List<Map<K,V>>

@Given("^i have the following user and password$")
public void dataMap02(List<Map<String, String>> userDetails) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
// throw new PendingException();
Iterator<Map<String, String>> it = userDetails.iterator();
while (it.hasNext()) {
Set<Entry<String, String>> set = it.next().entrySet();
Iterator<Entry<String, String>> mapIt = set.iterator();
while (mapIt.hasNext()) {
Entry<String, String> next = mapIt.next();
System.out.println(next.getValue());
System.out.println(next.getKey());
}
}

}

OUTPUT


# this feature file will illustrate how we can create data
# through Gherkin for the purpose of data driven test
Feature: generate data
like instiantiate the webDriver
user1
user2
user3
user4
something like destroying instance of webDriver
like instiantiate the webDriver

Scenario: from list # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:5
Given the following users: user1,user2,user3,user4 # DataStepDefinition.the_following_users_user_user_user_user(String>)
user_01
userName
password_01
password
user_02
userName
password_01
password
user_03
userName
password_01
password
something like destroying instance of webDriver

Scenario: from data table # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:8
Given i have the following user and password # DataStepDefinition.dataMap02(String,String>>)

2 Scenarios (2 passed)
2 Steps (2 passed)
0m0.131s

For complex data table Scenario




Scenario: create a table with multiple column and retieve data from several columns in step dfinations
Given I have the following customer information
| firstName | middleName | lastName | dob | userType | password | userName |
| sudas | s | das | 22-01-2015 | admin | admin1 | Allen |
| sdas | s | das | 15-01-2015 | user | admin2 | Dave |
| pdas | | das | 16-01-2015 | user | admin3 | Bob |

Create a user Model class


package com.sudas.wordpress.BDD.test.data.sd;

public class UserModel {

String firstName;
String middleName;
String lastName;
String dob;
String userType;
String password;
String userName;

public UserModel(String firstName, String middleName, String lastName, String dob, String userType, String password,
String userName) {
super();
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.dob = dob;
this.userType = userType;
this.password = password;
this.userName = userName;
}

public String getFirstName() {
return firstName;
}

public String getMiddleName() {
return middleName;
}

public String getLastName() {
return lastName;
}

public String getDob() {
return dob;
}

public String getUserType() {
return userType;
}

public String getPassword() {
return password;
}

public String getUserName() {
return userName;
}

}

Now in step definition method get the values like




 @Given("^I have the following customer information$")
public void i_have_the_following_customer_information(List<UserModel> users) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
// throw new PendingException();

System.out.println(users.get(0).getFirstName());
System.out.println(users.get(0).getLastName());
System.out.println(users.get(0).getMiddleName());
System.out.println(users.get(0).getUserName());
System.out.println(users.get(0).getPassword());
System.out.println(users.get(0).getUserType());
System.out.println(users.get(0).getDob());

}

OutPut


sudas
das
s
Allen
admin1
admin
22-01-2015
something like destroying instance of webDriver

Scenario: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:15
Given I have the following customer information

When to use what 

Use of data table

These steps are replaced by below data table

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 |



Then I should see a vehicle that matches the following description: 
| Wheels | 2 |
|MaxSpeed |60mph |
| Accessories | lights, shopping basket |



Then my shopping list should contain: | Onions |
| Potatoes |
| Sausages |
| Apples   |
| Relish   |


Use Of Scenario Outline

Sometimes you have several scenarios that follow exactly the same pattern of steps, just with different input values or expected outcomes. For example, suppose we are testing the user details for each users.  Instead of writing the multiple same scenario with only different set of data the same can be achieved through ScenarioOutline


Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations
Given the userConsole
When select the user <UserName>
Then the user should belong to company <Company>
And the user should belong to company <Org>
And the user should belong to company <Department>
And the user shoud have the email as <Email>
And the user account should not be disabled <IsDisabled>

Examples:
| UserName | Company | Org | Department | Email | IsDisabled |
| User_01 | ABC Corp. | ABC Org | R and D | User_01@abc.com | No |
| User_02 | Space X | Space Org | Accounts | User_02@sx.com | No |
| User_03 | Speed King | King's Org | Sales | User_03@sk.com | No |

And below is how the method will be implemented



# this feature file will illustrate how we can create data
# through Gherkin for the purpose of data driven test
Feature: generate data
like instiantiate the webDriver
user1
user2
user3
user4
something like destroying instance of webDriver
like instiantiate the webDriver

Scenario: from list # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:5
Given the following users: user1,user2,user3,user4 # DataStepDefinition.the_following_users_user_user_user_user(String>)
user_01
userName
password_01
password
user_02
userName
password_01
password
user_03
userName
password_01
password
something like destroying instance of webDriver
like instiantiate the webDriver

Scenario: from data table # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:8
Given i have the following user and password # DataStepDefinition.dataMap02(String,String>>)
Subhra
Sharanya
Pranati
something like destroying instance of webDriver

Scenario: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:15
Given I have the following customer information # DataStepDefinition.i_have_the_following_customer_information(UserModel>)

Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:22
Given the userConsole
When select the user <UserName>
Then the user should belong to company <Company>
And the user should belong to company <Org>
And the user should belong to company <Department>
And the user shoud have the email as <Email>
And the user account should not be disabled <IsDisabled>

Examples:
like instiantiate the webDriver
something like destroying instance of webDriver
like instiantiate the webDriver

Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:33
Given the userConsole
When select the user User_01
Then the user should belong to company ABC Corp.
And the user should belong to company ABC Org
And the user should belong to company R and D
And the user shoud have the email as User_01@abc.com
And the user account should not be disabled No
something like destroying instance of webDriver
like instiantiate the webDriver

Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:34
Given the userConsole
When select the user User_02
Then the user should belong to company Space X
And the user should belong to company Space Org
And the user should belong to company Accounts
And the user shoud have the email as User_02@sx.com
And the user account should not be disabled No
something like destroying instance of webDriver

Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:35
Given the userConsole
When select the user User_03
Then the user should belong to company Speed King
And the user should belong to company King's Org
And the user should belong to company Sales
And the user shoud have the email as User_03@sk.com
And the user account should not be disabled No

6 Scenarios (3 undefined, 3 passed)
24 Steps (21 undefined, 3 passed)
0m0.198s


You can implement missing steps with the snippets below:

@Given("^the userConsole$")
public void the_userConsole() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@When("^select the user User_(\\d+)$")
public void select_the_user_User_(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company ABC Corp\\.$")
public void the_user_should_belong_to_company_ABC_Corp() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company ABC Org$")
public void the_user_should_belong_to_company_ABC_Org() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company R and D$")
public void the_user_should_belong_to_company_R_and_D() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user shoud have the email as User_(\\d+)@abc\\.com$")
public void the_user_shoud_have_the_email_as_User__abc_com(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user account should not be disabled No$")
public void the_user_account_should_not_be_disabled_No() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company Space X$")
public void the_user_should_belong_to_company_Space_X() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company Space Org$")
public void the_user_should_belong_to_company_Space_Org() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company Accounts$")
public void the_user_should_belong_to_company_Accounts() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user shoud have the email as User_(\\d+)@sx\\.com$")
public void the_user_shoud_have_the_email_as_User__sx_com(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company Speed King$")
public void the_user_should_belong_to_company_Speed_King() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company King's Org$")
public void the_user_should_belong_to_company_King_s_Org() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user should belong to company Sales$")
public void the_user_should_belong_to_company_Sales() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}

@Then("^the user shoud have the email as User_(\\d+)@sk\\.com$")
public void the_user_shoud_have_the_email_as_User__sk_com(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}