My First Cucumber BDD project
Updated: Jan 13
Recently, I got an opportunity to work with a Selenium automation project with Cucumber. This experience helped in learning Behavior Driven Development and know about Cucumber. In this blog I am just writing about cucumber related features.
Introduction to Cucumber
Cucumber is an open-source tool which is used for Behavior Driven Development. It uses features files which are written in simple language and step definition files to handle code in a systematic way.
Steps in Cucumber Project
We started with creating scenarios in excel first and feature files, after that we created step definitions files and page objects files
Dependencies Required for Cucumber Project
Along with other selenium dependencies in pom xml we had to add cucumber related dependencies
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.26.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
These dependencies will help maven in downloading all the external cucumber libraries
Folder Structure in Cucumber Framework

Sample feature file
Feature: Array Functionality
Background:
Given The user is on the abc portal
When The user clicks "GetStarted" button on welcome page
And The user logs in with valid username and password
Then The user lands on the home page of abc portal
Scenario: Verify that "abc" label is displayed on the top left corner of the Array page module
Given The user is on Array Data Structure
Then The user sees "abc" label on the top left corner of the "Array" page module
Scenario: Verify the data structures dropdown is present on the top left corner of the Array page module
Given The user is on Array Data Structure
Then The user sees the "Data Structures" dropdown box on the top left corner of the "Array" page module
Scenario: Verify that link with "Sign out" label is displayed on the Array page module
Given The user is on Array Data Structure
Then The user sees "Sign out" link on the top right most corner of the "Array" page module
Scenario: Verify that link with username label is displayed on the Array page module
Given The user is on Array Data Structure
Then The user sees "Qatitans1" label on the top right corner of the "Array" page module
Scenario Outline: Verify that user sees header labels on various links from Array page
Given The user is on Array Data Structure
When The user clicks "<OptionOnArray>" link
Then The user sees "abc" label on the top left corner of the "Array" page module
And The user sees the "Data Structures" dropdown box on the top left corner of the "Array" page module
And The user sees "xyzzy" label on the top right corner of the "Array" page module
And The user sees "Sign out" link on the top right most corner of the "Array" page module
Examples:
| OptionOnArray |
| Arrays in Python |
| Arrays using List |
| Basic Operations in Lists |
| Applications of Array |
Sample StepDefinition File
package com.qa.abc.pages;
import java.time.Duration;
import java.util.List;
import org.openqa.selenium.Alert;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class ArrayPage {
@FindBy(xpath = "//a[@href='array']")
private WebElement arrayStartBtn;
@FindBy(xpath = "//div[@role='alert' and contains(text(), 'You are not logged in')]")
private WebElement notLoggedInMsg;
@FindBy(xpath = "//h4[@class='bg-secondary text-white']")
private WebElement arrayLabel;
@FindBy(xpath = "//a[normalize-space()='Arrays in Python']")
private WebElement arrPythonLink;
@FindBy(xpath = "//a[@class='nav-link dropdown-toggle']")
private WebElement dropdown;
@FindBy(xpath = "//a[@class='dropdown-item' and text()='Arrays']")
private WebElement arraysLinkItem;
@FindBy(xpath = "//a[@class='list-group-item']")
private List<WebElement> topicLinks;
@FindBy(xpath = "//h4")
private WebElement pageHeader;
@FindBy(xpath = "//a[@class='btn btn-info']")
private WebElement tryMeButton;
@FindBy(css = "div.CodeMirror-scroll")
private WebElement codeEditorTxtBx;
@FindBy(xpath = "//button[@type='button']")
private WebElement runBtn;
@FindBy(id = "output")
private WebElement outputMessage;
@FindBy(css = "textarea")
private WebElement codeMirrorTextArea;
@FindBy(xpath = "//a[text()='Practice Questions']")
private WebElement practiceQ;
@FindBy(xpath = "//a[normalize-space()='Search the array']")
private WebElement searchArrayQLink;
@FindBy(xpath = "//div[@id='navbarCollapse']//a[@href='/login']")
private WebElement signinLink;
@FindBy(name = "username")
private WebElement usernameTextbox;
@FindBy(name = "password")
private WebElement passwordTextbox;
@FindBy(xpath = "//form//input[@type='submit' and @value='Login']")
private WebElement loginButton;
@FindBy(xpath = "//a[@class='navbar-brand']")
private WebElement numpyNinjaLink;
@FindBy(xpath = "//a[text()='Data Structures']")
private WebElement dataStructuresDropdown;
@FindBy(xpath = "//div[@id='navbarCollapse']//a[@href='/register']")
private WebElement registerLink;
@FindBy(xpath = "//a[normalize-space()='Sign out']")
private WebElement signoutLink;
@FindBy(xpath = "//a[normalize-space()='Qatitans1']")
private WebElement usernameLabel;
private WebDriver driver;
public ArrayPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void clickStartBtn() {
arrayStartBtn.click();
}
public void clickArrayPythonLink() {
arrPythonLink.click();
}
public String getNotLoggedInMessage() {
return notLoggedInMsg.getText().trim();
}
public void clickLoginLink() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(signinLink));
signinLink.click();
}
public void userLoggedin() {
signinLink.click();
usernameTextbox.sendKeys("qatitans1");
passwordTextbox.sendKeys("1@Chicago");
loginButton.click();
}
public void selectArrayFrmDropdown() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
Actions actions = new Actions(driver);
wait.until(ExpectedConditions.elementToBeClickable(dropdown));
dropdown.click();
wait.until(ExpectedConditions.elementToBeClickable(arraysLinkItem));
((JavascriptExecutor) driver)
.executeScript("arguments[0].click();", arraysLinkItem);
wait.until(
ExpectedConditions.or(
ExpectedConditions.titleContains("Array"),
ExpectedConditions.urlContains("array")
)
);
}
public boolean arrayLabelDisplayed() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.visibilityOf(arrayLabel));
return arrayLabel.isDisplayed();
}
public String getTitleArraypage() {
return driver.getTitle();
}
public void clickTryMeButton() {
tryMeButton.click();
}
public void codeEditorSendKeys(String code) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.visibilityOf(codeEditorTxtBx));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.querySelector('.CodeMirror').CodeMirror.setValue('');");
js.executeScript(
"document.querySelector('.CodeMirror').CodeMirror.setValue(arguments[0]);",
code
);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void clickRunBtn() {
runBtn.click();
}
}
Sample Page Object file
package com.qa.abc.pages;
import java.time.Duration;
import java.util.List;
import org.openqa.selenium.Alert;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class ArrayPage {
@FindBy(xpath = "//a[@href='array']")
private WebElement arrayStartBtn;
@FindBy(xpath = "//div[@role='alert' and contains(text(), 'You are not logged in')]") // on home page
private WebElement ntloggedinMsg;
// locators from array module page
@FindBy(xpath = "//h4[@class='bg-secondary text-white']")
private WebElement arrayLabel;
@FindBy(xpath = "//a[normalize-space()='Arrays in Python']")
private WebElement arrPythonLink;
@FindBy(xpath = "//a[@class='nav-link dropdown-toggle']")
private WebElement dropdown;
@FindBy(xpath = "//a[@class='dropdown-item' and text()='Arrays']")
private WebElement arraysLinkItem;// from dropdown
@FindBy(xpath = "//a[@class='list-group-item']")
private List<WebElement> topicLinks; // locators for links on array module
@FindBy(xpath = "//h4")
private WebElement pageHeader;
@FindBy(xpath = "//a[@class='btn btn-info']")
private WebElement tryMeButton;
@FindBy(css = "div.CodeMirror-scroll")
private WebElement codeEditorTxtBx;
@FindBy(xpath = "//button[@type='button']")
private WebElement runBtn;
@FindBy(id = "output")
private WebElement outputMessage;
@FindBy(css = "textarea")
private WebElement codeMirrorTextArea;
@FindBy(xpath = "//a[text()='Practice Questions']")
private WebElement praticeQ;
@FindBy(xpath="//a[normalize-space()='Search the array']")
private WebElement searchArrayQLink;
@FindBy(xpath = "//div[@id='navbarCollapse']//a[@href='/login']")
private WebElement signinLink;
@FindBy(name = "username")
private WebElement usernametextbox;
@FindBy(name = "password")
private WebElement passwordtextbox;
@FindBy(xpath = "//form//input[@type='submit' and @value='Login']")
private WebElement loginButton;
@FindBy(xpath = "//a[@class='navbar-brand']")
private WebElement numpyNinjaLink;
@FindBy(xpath = "//a[text()='Data Structures']")
private WebElement dataStructuresDropdown;
@FindBy(xpath = "//div[@id='navbarCollapse']//a[@href='/register']")
private WebElement registerLink;
@FindBy(xpath = "//a[normalize-space()='Sign out']")
private WebElement signoutLink;
@FindBy(xpath = "//a[normalize-space()='Qatitans1']")
private WebElement usernameLabel;
private WebDriver driver;
public ArrayPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void clickStartBtn() {
arrayStartBtn.click();
}
public void clickArrayPythonLink() {
arrPythonLink.click();
}
public String getnotlogedMessage() {// this will go to home page as it shows on home page
return ntloggedinMsg.getText().trim();
}
public void clickLoginLink() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(signinLink));
signinLink.click();
}
public void userLoggedin() {
signinLink.click();
usernametextbox.sendKeys("qatitans1");
passwordtextbox.sendKeys("1@Chicago");
loginButton.click();
}
public void selectArrayFrmDropdown() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
Actions actions = new Actions(driver);
wait.until(ExpectedConditions.elementToBeClickable(dropdown));
dropdown.click();
wait.until(ExpectedConditions.elementToBeClickable(arraysLinkItem));
((JavascriptExecutor) driver).executeScript("arguments[0].click();", arraysLinkItem);
wait.until(
ExpectedConditions.or(ExpectedConditions.titleContains("Array"), ExpectedConditions.urlContains("array")
}
public boolean arrayLabelDisplayed() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.visibilityOf(arrayLabel));
return arrayLabel.isDisplayed();
}
public String getTitleArraypage() { // please check to remove duplicate methods
return driver.getTitle();
}
public void clickTryMeButton() {
tryMeButton.click();
}
public void codeEditorSendKeys(String code) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.visibilityOf(codeEditorTxtBx));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.querySelector('.CodeMirror').CodeMirror.setValue('');");
js.executeScript("document.querySelector('.CodeMirror').CodeMirror.setValue(arguments[0]);", code);
try {
Thread.sleep(500); // Small pause (not mandatory but helpful sometimes)
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void clickRunBtn() {
runBtn.click();
}
After we created the Feature files, step definition files and page object we created Hooks and Runner File so that we can run the tests.
Sample Hooks file
package com.qa.abc.stepdefinitions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import com.qa.abc.driverfactory.DriverManager;
import utilities.CommonUtils;
import io.cucumber.java.After;
import io.cucumber.java.AfterStep;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
public class Hooks {
public static WebDriver driver;
private static final Logger LOG=LogManager.getLogger(Hooks.class);
@Before
public void beforeScenario() {
try {
CommonUtils.loadProperties();
if(driver== null) {
driver = DriverManager.launchBrowser();
driver.manage().window().maximize();
}
LOG.info("Browser is launched");
}
catch (Exception e) {
e.printStackTrace();
}
}
@AfterStep
public void addScreenShot(Scenario scenario)
{
if(scenario.isFailed())
{
LOG.error("Scenario failed");
String ScreenShotName = scenario.getName().replaceAll(" ", "_");
byte[] sourcePath = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.attach(sourcePath, "image/png", ScreenShotName);
}
}
@After
public void tearDown() {
closeBrowser();
driver = null; // reset driver after test
}
@After
public static void closeBrowser() {
if (driver != null) {
driver.quit();
LOG.info("Browser session closed.");
}
}
public static WebDriver getDriver() {
return driver;
}
}
Sample Runner File
package runner;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(
plugin = {"pretty","io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm", "html:target/cucumber.html"},
features = "src/test/resources/features",
glue = {"com.qa.dsalgo.stepdefinitions.Hooks","com.qa.dsalgo.stepdefinitions" },
dryRun = false
)
public class TestRunner extends AbstractTestNGCucumberTests {
}
To run the tests, we can use two options we can run it by right clicking on runner file and choose to TestRunner option or you can run it from feature file. For running it from feature file open the feature file and right click, select Run As option and choose run as Cucumber feature option.
It was interesting and fun learning experience and I learned a lot about Cucumber and behavior driven development concepts. Cucumber is a great tool in eliminating gap between developers , testers and stakeholders and increasing team collaboration. I would like to thank Supritam Dass, Sumathi Selevraj , Kala Muthukrishnan and other mentors from NumpyNinja organization (https://www.numpyninja.com) for giving me this opportunity and guiding me. Thanks for reading my blog!


