This post will give a quick introduction to Cucumber-JVM and an easy-to-follow tutorial to start using Cucumber for writing and automating features.
Quick introduction to Cucumber
Cucumber is a BDD (Behavior Driven Development) framework originally written for Ruby. Cucumber-JVM is the pure Java implementation of Cucumber. Its quite matured now and has almost all the features available in original Cucumber implementation. Cucumber is less a test automation tool and more a collaboration tool between the business and technology people in the team. Cucumber supports describing the behavior of your system in a domain specific natural language called Gherkin. Cucumber features files written in Gherkin syntax act as documentation as well as automated acceptance tests.
How does a Cucumber feature looks like?
Feature: Title of your feature
In
order to <meet some goal>
As a
<type of stakeholder>
I
want <a feature>
Scenario: Title of the first scenario
Given <some context or precondition>
And <additional precondition> optional
When <some action is performed>
Then <some result or post condition>
And <additional post conditions> optional
Scenario: Title of the second scenario
...........
..........
How does it work?
Once the behavior of a system is written in feature files like above by the business/solution analysts, developers/test engineers will write the underlying glue code (or step definitions) to actually test the system. The glue code can be direct calls to application code or calls to other libraries/APIs (like WebDriver, RestAssured, etc) depending on the application and type of test.
In this blog we are going to write and automate acceptance tests using Cucumber and Selenium WebDriver for a simple WikiPedia search functionality.
Create and configure your project in Eclipse
Create a new Maven project in Eclipse with below details:
Archetype: maven-archetype-quickstart
Group Id: com.cucumber
Artifact Id: learncucumber
Your project structure in "Package Explorer" will look like below:
Add a new source folder "src/test/resources" in the project and then add a new folder named "features" under this source folder. Your project will now look like below:
Now edit the pom.xml, add below two dependencies and save the pom.xml:
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-java -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
</dependency>
All the required jars for Cucumber and WebDriver will be downloaded. Now add a new folder named "drivers" in "src/test/resources" source folder, download and place "chromedriver.exe" in this folder. Project will look like below:
Now the project is ready to add our first feature file and automate it.
Add a new feature file
Before we add our first Cucumber feature file, we need to install cucumber-eclipse plugin from update site https://cucumber.io/cucumber-eclipse/update-site
Add a new file named "SearchCountry.feature" in the "src/test/resources/features" folder. The cucumber-eclipse plugin will create the SearchCountry.feature file with an example Gherkin feature file as shown below:
Add a new file named "SearchCountry.feature" in the "src/test/resources/features" folder. The cucumber-eclipse plugin will create the SearchCountry.feature file with an example Gherkin feature file as shown below:
Change the content of the file to below text:
#This
feature enables a user search for country names
Feature:
Search for country names
In order to know about few countries
As a user
I want to search few country names
#First
scenario
Scenario:
Search for an Asian country
Given I am on Main Page
When I search for country "India"
Then I verify "India" displays in the header
In the eclipse IDE all of the above three steps will appear in a yellow color (with warning sign) indicating the steps do not have matching glue code as shown below.
Right click on the feature file in the editor and "Run As" Cucumber Feature. Once run, the console will print below log:
1 Scenarios (1 undefined)
3 Steps (3 undefined)
You can implement missing steps with the snippets below:
@Given("^I am on Main Page$")
public void i_am_on_Main_Page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
@When("^I search for country \"([^\"]*)\"$")
public void i_search_for_country(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
@Then("^I verify \"([^\"]*)\" displays in the header$")
public void i_verify_displays_in_the_header(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
Write the glue code (step implementation)
Create a new java class named "WikipediaStepDefinitions" in the "com.cucumber.learncucumber" package of "learncucumber/src/test/java" source folder and copy and paste the code snippets from console. Save the file. If you run the feature again you will see below result in console:
Feature: Search for country names
In order to know about few countries
As a user
I want to search few country names
#First scenario
Scenario: Search for an Asian country # C:/workspace/cucumber/learncucumber/src/test/resources/features/SearchCountry.feature:7
Given I am on Main Page # WikipediaStepDefinitions.i_am_on_Main_Page()
cucumber.api.PendingException: TODO: implement me
at com.cucumber.learncucumber.WikipediaStepDefinitions.i_am_on_Main_Page(WikipediaStepDefinitions.java:17)
at ?.Given I am on Main Page(C:/workspace/cucumber/learncucumber/src/test/resources/features/SearchCountry.feature:8)
When I search for country "India" # WikipediaStepDefinitions.i_search_for_country(String)
Then I verify "India" displays in the header # WikipediaStepDefinitions.i_verify_displays_in_the_header(String)
1 Scenarios (1 pending)
3 Steps (2 skipped, 1 pending)
Feature: Search for country names
In order to know about few countries
As a user
I want to search few country names
#First scenario
Scenario: Search for an Asian country # C:/workspace/cucumber/learncucumber/src/test/resources/features/SearchCountry.feature:7
Given I am on Main Page # WikipediaStepDefinitions.i_am_on_Main_Page()
cucumber.api.PendingException: TODO: implement me
at com.cucumber.learncucumber.WikipediaStepDefinitions.i_am_on_Main_Page(WikipediaStepDefinitions.java:17)
at ?.Given I am on Main Page(C:/workspace/cucumber/learncucumber/src/test/resources/features/SearchCountry.feature:8)
When I search for country "India" # WikipediaStepDefinitions.i_search_for_country(String)
Then I verify "India" displays in the header # WikipediaStepDefinitions.i_verify_displays_in_the_header(String)
1 Scenarios (1 pending)
3 Steps (2 skipped, 1 pending)
This is because the only thing our implementation methods do is to throw an exception indicating that implementation of these methods are still pending. Lets complete the implementation.
We need to launch a browser before executing our scenario - the best way to do that in Cucumber is to use a separate method annotated with @Before which will be executed before each scenario execution. This is similar to using @Before in JUnit and is called a "hook" in Cucumber. We will also use @After hook to quit a browser. Final implementation of "WikipediaStepDefinitions" will be as below:
package com.cucumber.learncucumber;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import junit.framework.Assert;
public class WikipediaStepDefinitions {
WebDriver driver;
@Before
public void launchBrowser(){
System.setProperty("webdriver.chrome.driver", "src/test/resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
}
@Given("^I am on Main Page$")
public void i_am_on_Main_Page() throws Throwable {
driver.get("https://en.wikipedia.org/wiki/Main_Page");
}
@When("^I search for country \"([^\"]*)\"$")
public void i_search_for_country(String countryName) throws Throwable {
WebElement searchField = driver.findElement(By.id("searchInput"));
WebElement searchButton = driver.findElement(By.id("searchButton"));
searchField.sendKeys(countryName);
searchButton.click();
}
@Then("^I verify \"([^\"]*)\" displays in the header$")
public void i_verify_displays_in_the_header(String countryName) throws Throwable {
WebElement headerField = driver.findElement(By.id("firstHeading"));
Assert.assertEquals(countryName, headerField.getText());
}
@After
public void quitBrowser(){
driver.quit();
}
}
Run the feature again and it will pass this time.
Make the code better
We have direct calls to WebDriver API in our "WikipediaStepDefinitions" class above. This is certainly not a good way to write your step implementation. Now lets refactor and place our WebDriver calls in PageObject classes. Refactored and improved project code is available in https://github.com/pradip79/learn-cucumber.git
Now add new scenarios to the existing feature file or add new feature file with new scenarios and automate those. Comment if you need additional info..
Now add new scenarios to the existing feature file or add new feature file with new scenarios and automate those. Comment if you need additional info..