This is a tutorial / technical writing about behaviour driven test (BDD) using Cucumber (Gherkin)
Installing Cucumber -
- Eclipse update site Cucumber - http://cucumber.github.com/cucumber-eclipse/update-site
This plugin is required for creating feature file/ BDD editor
- Cucumber JARs for maven repo http://mvnrepository.com/artifact/info.cukes
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 @CucumberOptionsFollowing 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
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.
'
Scenario 1: from list and
Scenario 2: from data table
This step definition is for the Feature -> scenario : from list
This step definition is for Feature "From data table"Step Definition method for data table using Map<String, String>
Step Definition method for data table using List<Map<K,V>>
OUTPUT
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 scenarioScenario 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"
@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 tableThese 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();
}