Cucumber is an open-source testing tool used for Behavior-Driven Development (BDD). It allows teams to describe application behavior in plain text that both technical and non-technical stakeholders can understand. The primary goal of Cucumber is to bridge the gap between business and technical teams by using a common language, Gherkin, which defines test scenarios in a readable and structured format.
Need Of Using Cucumber : Cucumber brings developers, testers, and non-technical stakeholders onto the same page. Using Gherkin language ensures that all team members understand the requirements and tests.
Cucumber uses the Gherkin language, which includes specific keywords to write feature files. These keywords help define the structure and logic of scenarios and features in plain text. Here's a list of the primary keywords in Cucumber:
-
Feature
-
Represents a high-level description of the functionality being tested.
-
Acts as the title for the feature file.
-
Example:
Feature: Login functionality As a user I want to log in to the system So that I can access my dashboard
-
-
Scenario
-
Describes a specific example or use case of the feature being tested.
-
Consists of a series of steps written in Given-When-Then format.
-
Example:
Scenario: Successful login Given the user is on the login page When the user enters valid credentials Then the user is redirected to the home page
-
-
Scenario Outline
-
Used for parameterized or data-driven testing, allowing the same scenario to be tested with multiple sets of data.
-
Paired with Examples to define the test data.
-
Example:
Scenario Outline: Login with multiple credentials Given the user is on the login page When the user enters "<username>" and "<password>" Then the user should see "<result>" Examples: | username | password | result | | valid_user | valid_pass | home page | | invalid_user | valid_pass | error message |
-
-
Given
-
Sets up the initial context or preconditions for the scenario.
-
Example:
Given the user is on the login page
-
-
When
-
Describes the action or event performed by the user.
-
Example:
When the user enters valid credentials
-
-
Then
-
Defines the expected outcome or result of the action.
-
Example:
Then the user is redirected to the home page
-
-
And
-
Used to add additional steps for Given, When, or Then.
-
Example:
Given the user is on the login page And the user has a valid account
-
-
But
-
Adds a negative or contrasting step to a scenario.
-
Example:
Then the user should see an error message But the system should not lock the account
-
-
Background
-
Defines common preconditions or steps that are shared by all scenarios in a feature.
-
Runs before each scenario in the feature file.
-
Example:
Background: Given the user is on the login page
-
-
Examples
-
Provides the test data for a Scenario Outline.
-
Written as a table of input values and expected results.
-
Example:
Examples: | username | password | | valid_user | valid_pass | | invalid_user | valid_pass |
-
-
Rule (Optional)
-
Used to group related scenarios and provide additional structure to feature files.
-
Example:
Rule: Login with valid credentials Scenario: Successful login ...
-
-
Doc Strings
-
Used to handle multi-line text data.
-
Example:
When the user submits the following data: """ { "username": "test_user", "password": "test_pass" } """
-
-
Tags
-
Used to group scenarios for selective execution.
-
Example:
@smoke Scenario: Successful login ...
-
These keywords allow non-technical stakeholders to understand and contribute to the requirements while enabling developers and testers to implement automated tests.
In Cucumber, a Feature represents a high-level functionality or a system behavior that you want to test. It serves as a container for multiple Scenarios, each describing specific test cases for that feature.
A Feature file is written in the Gherkin language and contains both a Feature description and one or more Scenarios or Scenario Outlines.
Feature Title: Login Functionality
Description: Ensures that users can log in using valid credentials and cannot log in using invalid ones.
Business Value: Provides secure access to the application for authorized users.
Feature: Login Functionality
As a registered user
I want to log in to the system
So that I can access my account and use the services.
Scenario: Successful login
Given the user is on the login page
When the user enters valid credentials
Then the user is redirected to the home page
Scenario: Unsuccessful login with invalid credentials
Given the user is on the login page
When the user enters invalid credentials
Then the user sees an error message- Located in the
featuresDirectory: Feature files are saved in thesrc/test/resources/featuresfolder by convention, with a.featureextension. - Written in Plain English: They use simple, descriptive language so they can serve as a live document for the project.
- Linked to Step Definitions: Each step in a scenario corresponds to a method in the step definition file, where automation code is implemented.
Step Definitions in Cucumber are Java methods that provide the underlying code implementation for the steps defined in a Gherkin Feature file. These methods bridge the gap between human-readable test steps written in Gherkin and the actual automation code executed during testing.
- Automation Implementation: They contain the Selenium, REST Assured, or other automation framework code to perform actions or validations.
- Link Gherkin to Code: Each Gherkin step (e.g.,
Given,When,Then) is matched with a corresponding Step Definition method using annotations like@Given,@When, and@Then. - Reusability: Step Definitions are reusable across multiple scenarios in the same or different Feature files.
A Step Definition has the following components:
- Annotation: Defines the type of step (
@Given,@When,@Then) and a regular expression to match the step text. - Method Body: Contains the code to execute for the corresponding step.
Feature: Login Functionality
Scenario: Successful login
Given the user is on the login page
When the user enters valid credentials
Then the user is redirected to the home page
package stepdefs;
import io.cucumber.java.en.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class LoginSteps {
WebDriver driver;
@Given("the user is on the login page")
public void the_user_is_on_the_login_page() {
driver = new ChromeDriver();
driver.get("https://www.saucedemo.com/");
driver.manage().window().maximize();
}
@When("the user enters valid credentials")
public void the_user_enters_valid_credentials() {
WebElement usernameField = driver.findElement(By.id("user-name"));
usernameField.sendKeys("standard_user");
WebElement passwordField = driver.findElement(By.id("password"));
passwordField.sendKeys("secret_sauce");
}
@Then("the user is redirected to the home page")
public void the_user_is_redirected_to_the_home_page() {
boolean isLogoDisplayed = driver.findElement(By.className("app_logo")).isDisplayed();
if (!isLogoDisplayed) {
throw new AssertionError("User is not on the home page");
}
driver.quit();
}
}- Annotations Link Steps:
@Given,@When,@Thenmatch the steps in the Feature file.- The regular expression in the annotation determines which Gherkin step the method corresponds to.
- Reusability: Step Definitions can be reused across multiple scenarios if the steps are identical.
- Independent of Order: Steps in the Feature file do not need to follow the order of methods in the Step Definition file.
- Cucumber Reads the Feature File: Parses the Gherkin steps and searches for corresponding Step Definitions.
- Regular Expression Matching: Matches the step text with the regex provided in the Step Definition annotation.
- Executes the Code: Executes the method body when the step is run during test execution.
A typical Cucumber framework is structured to support Behavior-Driven Development (BDD) and includes various types of files and configurations. Below is a list of essential files needed:
-
Purpose: Contain test scenarios written in Gherkin syntax.
-
Location: Typically located in the
src/test/resources/featuresdirectory. -
Example:
Feature: Login Functionality Scenario: Successful login Given the user is on the login page When the user enters valid credentials Then the user is redirected to the home page
-
Purpose: Provide the implementation (code) for the steps defined in Feature files.
-
Location: Typically located in the
src/test/java/stepdefspackage. -
Example:
package stepdefs; import io.cucumber.java.en.*; public class LoginSteps { @Given("the user is on the login page") public void userIsOnLoginPage() { System.out.println("Navigating to the login page"); } @When("the user enters valid credentials") public void userEntersValidCredentials() { System.out.println("Entering username and password"); } @Then("the user is redirected to the home page") public void userRedirectedToHomePage() { System.out.println("Validating home page redirection"); } }
-
Purpose: Integrates the framework, specifying paths for Feature files and Step Definitions. It configures Cucumber execution options.
-
Location: Typically located in the
src/test/javadirectory. -
Example:
package TestRunner; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions( features = "src/test/resources/features", glue = "stepdefs", plugin = {"pretty", "html:target/cucumber-reports.html"} ) public class TestRunner { }
- Purpose: Store reusable configurations for the framework.
- Examples:
-
config.properties: Contains environment-specific configurations like URLs, credentials, etc.-
Example:
baseURL=https://www.saucedemo.com username=standard_user password=secret_sauce
-
-
log4j.properties(optional): Configures logging.-
Example:
log4j.rootLogger=DEBUG, FILE log4j.appender.FILE=org.apache.log4j.FileAppender log4j.appender.FILE.File=logs/application.log
-
-
- Purpose: Manages dependencies and build configurations.
- Examples:
pom.xml(for Maven):-
Example:
<dependencies> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>7.11.0</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.11.0</version> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-testng</artifactId> <version>7.11.0</version> </dependency> </dependencies>
-
-
Purpose: Define actions to execute before or after each scenario (e.g., setup, teardown).
-
Location: Typically in the
src/test/java/hookspackage. -
Example:
package hooks; import io.cucumber.java.After; import io.cucumber.java.Before; public class Hooks { @Before public void setup() { System.out.println("Setup before the scenario"); } @After public void teardown() { System.out.println("Teardown after the scenario"); } }
- Purpose: Contain reusable functions like WebDriver initialization, screenshot capturing, or file reading.
- Examples:
-
DriverFactory.java:package utils; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class DriverFactory { private static WebDriver driver; public static WebDriver getDriver() { if (driver == null) { driver = new ChromeDriver(); } return driver; } }
-
- Purpose: Stores the reports generated by Cucumber after test execution.
- Location:
target/orreports/directory.
- Purpose: Store additional resources like test data or environment variables.
- Examples:
data.jsontestdata.xlsx
src
├── main
├── test
│ ├── java
│ │ ├── stepdefs
│ │ │ └── LoginSteps.java
│ │ ├── hooks
│ │ │ └── Hooks.java
│ │ ├── TestRunner
│ │ │ └── TestRunner.java
│ │ ├── utils
│ │ │ └── DriverFactory.java
│ ├── resources
│ │ ├── features
│ │ │ └── Login.feature
│ │ ├── config.properties
│ └── target
│ └── cucumber-reports.html
pom.xml
This structure ensures maintainability, modularity, and scalability in your Cucumber framework.
The @CucumberOptions annotation in the Cucumber framework is used to configure and customize the execution of Cucumber tests. It is applied to the Test Runner class and serves as a way to specify various properties that control how feature files are executed, where step definitions are located, and how reports are generated.
- Purpose: Specifies the path to the directory or file containing Cucumber feature files.
- Example:
This ensures that all feature files in the features folder are executed.
```java
@CucumberOptions(features = "src/test/resources/features")
```
- Purpose: Specifies the package or packages containing step definitions and hooks.
- Example:
This links the feature files to their corresponding step definitions.
```java
@CucumberOptions(glue = "stepdefs")
```
-
Purpose: Defines the reporting format and where the reports will be saved.
-
Common Plugins:
"pretty": Prints the steps and results in a readable format."html:target/cucumber-reports.html": Generates an HTML report in the specified location."json:target/cucumber-reports.json": Generates a JSON report for further analysis."junit:target/cucumber-reports.xml": Generates a JUnit XML report.
-
Example:
@CucumberOptions(plugin = {"pretty", "html:target/cucumber-reports.html"})
- Purpose: Filters which scenarios to execute based on tags in the feature files.
- Example:
This runs only the scenarios marked with the @SmokeTest tag.
```java
@CucumberOptions(tags = "@SmokeTest")
```
-
Purpose: Makes the console output more readable by removing unnecessary characters or colors.
-
Example:
@CucumberOptions(monochrome = true)
-
Purpose: Checks the mapping between feature file steps and step definitions without executing the test steps. Useful for verifying that all steps are implemented.
-
Example:
@CucumberOptions(dryRun = true)
-
Purpose: Filters scenarios to execute based on their names.
-
Example:
@CucumberOptions(name = {"Login Functionality", "Signup Flow"})
package TestRunner;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features", // Path to feature files
glue = "stepdefs", // Path to step definitions
plugin = {"pretty", "html:target/cucumber-reports.html"}, // Reporting
tags = "@SmokeTest", // Run scenarios with specific tags
monochrome = true, // Cleaner console output
dryRun = false // Validate steps without running tests
)
public class TestRunner {
}- Customization: Allows precise control over which tests to run, how they are executed, and how results are reported.
- Scalability: Enables filtering and organizing tests in large-scale projects.
- Debugging: With options like
dryRun, you can quickly identify unimplemented steps. - Integration: Facilitates integration with CI/CD pipelines by generating JSON or XML reports.
Cucumber execution begins with the support level, following a specific loading order:
env.rbfile:- This file contains environment configurations or global setup required for the tests, such as browser setup, environment variables, or other initializations.
hooks.rbfile:- Contains hooks like
Before,After, orAroundblocks that execute before, after, or around the scenarios. These are used for tasks such as setting up data, cleaning up, or logging.
- Contains hooks like
- Feature File Scenario Steps:
- Once the support files are loaded, Cucumber starts executing the steps defined in the feature file, mapping them to the respective step definitions in the code.
Grouping in Cucumber refers to the practice of organizing step definitions into separate files based on their functionality or purpose. Instead of maintaining all step definitions in a single file, they are split into multiple files, such as login_steps.rb or checkout_steps.rb.
- Improved Organization: Steps are grouped logically by feature or functionality.
- Better Maintenance: Easier to update or debug step definitions without affecting unrelated parts.
- Scalability: Makes the framework manageable for large projects with multiple features.
Example of Grouping:
features/login.feature: Contains scenarios for login functionality.stepdefs/LoginSteps.java: Step definitions for login-related steps.features/checkout.feature: Contains scenarios for checkout functionality.stepdefs/CheckoutSteps.java: Step definitions for checkout-related steps.
To execute Cucumber tests in parallel, you can use tools or plugins like the Cucumber JVM Parallel Plugin or TestNG. These plugins divide the feature files or scenarios across multiple threads, enabling parallel execution.
-
Setup: Add the plugin to your
pom.xmlfor Maven projects.<plugin> <groupId>com.github.temyers</groupId> <artifactId>cucumber-jvm-parallel-plugin</artifactId> <version>5.0.0</version> <executions> <execution> <id>generateRunners</id> <phase>generate-test-sources</phase> <goals> <goal>generateRunners</goal> </goals> </execution> </executions> </plugin>
-
Feature File Directory:
Ensure your feature files are in the
src/test/resourcesdirectory. -
Generated Runners:
The plugin will create separate runners for each feature file in the
target/generated-test-sourcesdirectory. -
Execution:
Use a parallel test execution framework like TestNG or JUnit to run the generated runners.
-
Modify
TestNG.xml: Configure parallel execution in the TestNG suite file.<suite name="Cucumber Suite" parallel="classes" thread-count="4"> <test name="Test"> <classes> <class name="TestRunner.TestRunner"/> </classes> </test> </suite>
-
Execution:
Run the TestNG suite file to execute tests in parallel.
- Faster Execution: Reduces the total test execution time by utilizing multiple threads.
- Scalability: Handles larger test suites more efficiently.
- Resource Utilization: Makes better use of available system resources.
By combining plugins like Cucumber JVM Parallel Plugin and test execution frameworks like TestNG or Serenity BDD, you can achieve efficient parallel test execution in Cucumber.
In Cucumber, you can use tags to selectively execute specific scenarios or exclude them from execution. This functionality is managed in the @CucumberOptions section of the TestRunner file.
-
Tagging Scenarios in the Feature File: You can add one or more tags to scenarios in your feature file. Tags start with the
@symbol and are placed above the scenario definition.Example:
@smoke Feature: Login Feature @positive Scenario: Verify valid login Given User is on login page When User enters valid username and password Then User is navigated to the Home Page @negative Scenario: Verify invalid login Given User is on login page When User enters invalid username and password Then User sees an error message
-
Configuring Tags in the TestRunner File: Use the
tagsparameter in the@CucumberOptionsannotation to specify which tests to include or exclude.Run Tests with a Specific Tag:
-
To run only the
@smokescenarios:@CucumberOptions( features = {"src/test/resources/features"}, glue = {"stepdefs"}, tags = "@smoke", plugin = {"pretty", "html:target/htmlReport.html"} ) public class TestRunner {}
Exclude Tests with a Specific Tag:
-
To run all tests except those with
@negative:@CucumberOptions( features = {"src/test/resources/features"}, glue = {"stepdefs"}, tags = "not @negative", plugin = {"pretty", "html:target/htmlReport.html"} ) public class TestRunner {}
Combine Multiple Tags:
-
To run tests with either
@smokeor@positive:tags = "@smoke or @positive"
-
To run tests with both
@smokeand@positive:tags = "@smoke and @positive"
-
- Selective Execution: Enables running specific tests, such as smoke, regression, or critical scenarios.
- Improved Test Management: Helps organize and segregate test cases based on functionality, priority, or execution type.
- Flexibility: Allows excluding specific tests temporarily without modifying feature files.
By using tags effectively, you can customize the execution of your test suite, focusing on relevant scenarios while maintaining clear and organized test structures.
bdd-pom-project/
│
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── pages/ # Page Object Classes
│ │ │ ├── utils/ # Utility Classes (e.g., WebDriver management, configs)
│ │ ├── resources/ # Application-specific resources
│ │
│ ├── test/
│ │ ├── java/
│ │ │ ├── stepdefs/ # Step Definitions
│ │ │ ├── runners/ # Test Runner Classes
│ │ │ ├── hooks/ # Hooks (Before, After annotations)
│ │ │ ├── testdata/ # Test Data or Test Utility
│ │ ├── resources/
│ │ │ ├── features/ # Feature Files
│ │ │ ├── config/ # Test Configurations (e.g., properties, environment settings)
│ │
├── target/ # Generated reports, compiled classes, etc.
│
├── pom.xml # Maven Configuration File
├── README.md # Project Documentation
└── .gitignore # Git Ignore FileHere are the required dependencies with use cases for a BDD project with Cucumber and POM:
- Cucumber Java
- Use case: Provides the core functionality for running Cucumber tests in Java. It connects the feature files with step definitions.
- Cucumber TestNG
- Use case: Integrates Cucumber with TestNG, allowing you to run tests and generate reports using TestNG. If you're using TestNG as a test runner, you’ll need this.
- Selenium WebDriver
- Use case: Required for web automation. WebDriver allows Cucumber to interact with browsers, performing actions like clicking buttons, entering text, etc., as per the scenarios.
- TestNG
- Use case: Used as a test runner. TestNG can be configured to run Cucumber feature files and generate detailed reports. It's especially useful when working with parallel test execution or creating customized reports.
- Cucumber JUnit (optional, if using JUnit)
- Use case: If you're using JUnit instead of TestNG, this dependency integrates Cucumber with JUnit, allowing you to run Cucumber tests in a JUnit environment.
- JUnit (optional, if using JUnit)
- Use case: The testing framework if you choose to run Cucumber tests with JUnit instead of TestNG.
- Apache POI (optional)
- Use case: Enables reading and writing data from Excel files. Useful for parameterizing tests, reading input data from external sources like Excel sheets.
- Maven Surefire Plugin
- Use case: Required for executing the tests in a Maven-based project. It ensures tests are picked up and executed during the build lifecycle.
- Allure Reports (optional)
- Use case: For generating visually appealing and detailed test execution reports. It integrates well with TestNG or JUnit to produce advanced reports showing test statuses and execution times.
These dependencies, when combined, provide a complete framework for running BDD tests with Cucumber in a Maven-managed project, ensuring both automated testing and well-documented reports.
💡
This note was curated by Dinesh. If you found it helpful or would like to share suggestions, fixes, or feedback, feel free to reach out to me: