Feature File
Feature: Login functionality
Scenario: Successful login with valid credentials
Given user is on login page
When user enters username "admin" and password "admin123"
And user clicks on login button
Then user should be navigated to home page
Step Defination File
import io.cucumber.java.en.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.junit.Assert;
public class LoginSteps {
WebDriver driver;
@Given("user is on login page")
public void user_is_on_login_page() {
driver = new ChromeDriver();
driver.get("https://example.com/login");
}
@When("user enters username {string} and password {string}")
public void user_enters_credentials(String username, String password) {
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
}
@And("user clicks on login button")
public void user_clicks_login_button() {
driver.findElement(By.id("loginBtn")).click();
}
@Then("user should be navigated to home page")
public void user_should_be_on_home_page() {
Assert.assertTrue(driver.getTitle().contains("Home"));
driver.quit();
}
}
A Scenario is used for a single test with fixed data, while a Scenario Outline is used for data‑driven testing where the same scenario runs multiple times using different values from an Examples table.
Given‑When‑Then is a format used in Cucumber to write test scenarios in a simple, readable way that describes system behavior.
The Given step is used to describe the initial state or precondition of the system. It sets up what is required before the test action happens. In my project, Given is used to prepare test data, set up API endpoints, or define a logged‑in user state.
The When step describes the action performed by the user or system. This is where the actual operation happens. In my project, When is used to make an API call such as sending a GET or POST request.
The Then step describes the expected outcome or result. This is where validations are done. In my project, Then is used to verify response status codes, response body values, or business rules.
In simple terms, Given sets the context, When performs the action, and Then verifies the result.
A Scenario Outline in Cucumber is used when the same test scenario needs to be executed multiple times with different input data.
Instead of writing the same scenario again and again, Scenario Outline allows you to define the scenario once and run it with multiple sets of data.
The scenario uses placeholders for values, and the actual data is provided in an Examples section. Cucumber runs the scenario once for each row of data in the Examples table.
In simple terms, Scenario Outline helps in data‑driven testing in Cucumber.
Example explanation in words
If you want to test a login feature with multiple usernames and passwords, you write one Scenario Outline and provide different username and password values in the Examples section. Cucumber will execute the scenario separately for each set of values.
Annotations in Cucumber are special tags or keywords used to control how scenarios are executed and how test setup and cleanup are handled.
Cucumber annotations like Given, When, Then, And, and But are used to define the steps of a scenario. They connect the steps written in feature files to the actual code implementation.
Cucumber also provides hook annotations such as Before and After. These are used to run setup code before a scenario starts and cleanup code after a scenario ends. In my project, Before is used to initialize request setup or test data, and After is used to clean up or log results.
Tags are also considered annotations in Cucumber. They are written with the @ symbol above scenarios or feature files. Tags are used to group scenarios and control which scenarios should be executed, for example running only smoke or regression tests.
In simple terms, annotations in Cucumber help define steps, manage test flow, and control execution.
A profile in Cucumber is a way to define how and what tests should be executed without changing the test code.
A Cucumber profile allows you to group execution settings such as feature file locations, glue code paths, tags, plugins, and reporting options under a single profile name.
Profiles are usually defined in a configuration file like cucumber.properties, cucumber.yml, or sometimes in the build tool configuration. Once defined, you can run a specific profile from the command line.
In my project, we used Cucumber profiles to run different test sets like smoke tests, regression tests, or environment‑specific executions by changing only the profile name.
In simple terms, a Cucumber profile helps control test execution behavior using predefined settings.
To integrate more than one feature file in Cucumber, we do not write separate runners for each file. Instead, we configure the test runner to pick multiple feature files together.
The most common way is by placing all feature files inside a single folder. In the runner file, we provide the path of that folder. Cucumber will automatically execute all feature files present in that folder.
Another way is by specifying multiple feature file paths in the runner configuration. This allows us to explicitly list which feature files should be executed together.
We can also integrate multiple feature files using tags. By adding common tags to scenarios or feature files and mentioning those tags in the runner, only the tagged scenarios from multiple feature files will be executed.
In real projects, we usually organize feature files by modules inside folders and use a single runner with folder paths and tags to control execution.
Data table implementation in Cucumber is used when you want to pass multiple values in a table format to a step definition.
A data table allows you to send structured data from a feature file to the step implementation without hard‑coding values in the code.
In the feature file, the data table is written below a step in rows and columns. This table represents input data that the step can use.
In the step definition, Cucumber converts the data table into a usable format such as a list or map, which can then be used in the test logic.
In my project, data tables were mainly used to pass multiple request values such as headers, query parameters, or request body fields in API testing. This helped avoid writing separate steps for each value and made the scenarios more readable.
In simple terms, a data table helps pass multiple data values to a single step in a clean and readable way.
Background and hooks in Cucumber are both used to set up conditions before scenarios run, but they are used for different purposes and at different levels.
Background is written inside the feature file. It contains steps that are common to all scenarios in that feature. These steps are business‑readable and describe actions that are part of the user flow, such as logging into an application. The background runs before every scenario in that feature file.
Hooks are written in the step definition code, not in the feature file. They are used for technical setup and cleanup tasks like launching or closing browsers, initializing API configurations, setting up test data, or cleaning up after execution. Hooks run before or after scenarios regardless of the feature file content.
In execution order, hooks run first, then background steps run, and then the actual scenario steps are executed.
In simple terms, background is used for common business steps visible to stakeholders, while hooks are used for technical setup and teardown that should not appear in the feature file.
In Cucumber, we can reuse data in multiple steps of the same scenario by storing the data at runtime and retrieving it in later steps.
The most common way is by using instance variables in the step definition class. When a value is captured in one step, it is stored in a class‑level variable, and the same variable can be accessed by other steps within the same scenario. Since Cucumber creates a new instance of the step definition class for each scenario, the data is safely shared only within that scenario.
Another common approach is using a scenario context or test context object. In this approach, data is stored in a shared context as key‑value pairs in one step and retrieved in another step. This is very useful when multiple step definition classes need access to the same data.
If dependency injection is used, a shared data object can be injected into multiple step classes. The data is set in one step and reused in other steps within the same scenario.
In simple terms, data is reused by storing it during one step execution and accessing it again in later steps of the same scenario.
A Scenario in Cucumber is used when you want to execute a test only once with a single set of data. The steps are written with fixed values, and the scenario runs one time exactly as written.
A Scenario Outline is used when the same scenario needs to be executed multiple times with different sets of data. Instead of hard‑coding values, placeholders are used in the steps, and the actual data is provided in an Examples section. Cucumber runs the scenario once for each row of data in the Examples.
In simple terms, Scenario is for single execution with fixed data, while Scenario Outline is for multiple executions with different data.