This is where it all clicks. You write a feature file in English, then create Java methods that automate each step. Cucumber reads the English, finds the matching Java method, and executes it. Let us build the Banking Portal login test end to end.
@banking @login
Feature: Banking Portal Login
As a bank customer
I want to log in to the banking portal
So that I can access my account
Background:
Given the user is on the Banking Portal login page
@smoke
Scenario: Successful login with valid credentials
When the user enters username "testuser"
And the user enters password "password123"
And the user clicks the login button
Then the user should be redirected to the dashboard
And the welcome message should contain "Welcome"
@regression
Scenario: Login fails with invalid password
When the user enters username "testuser"
And the user enters password "wrongpassword"
And the user clicks the login button
Then an error message "Invalid credentials" should be displayed
@regression
Scenario: Login fails with empty username
When the user leaves the username field empty
And the user enters password "password123"
And the user clicks the login button
Then an error message "Username is required" should be displayedEach line in the feature file maps to a Java method. Cucumber matches the text using annotations — @Given, @When, @Then, @And. Parameters in curly braces ({string}, {int}) capture values from the step text.
package com.autopractice.stepdefinitions;
import com.autopractice.hooks.Hooks;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import java.time.Duration;
public class LoginSteps {
private WebDriver driver;
private WebDriverWait wait;
public LoginSteps() {
this.driver = Hooks.getDriver();
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
@Given("the user is on the Banking Portal login page")
public void userIsOnLoginPage() {
driver.get("https://www.testerrank.com/banking");
}
@When("the user enters username {string}")
public void userEntersUsername(String username) {
driver.findElement(By.id("username")).sendKeys(username);
}
@When("the user enters password {string}")
public void userEntersPassword(String password) {
driver.findElement(By.id("password")).sendKeys(password);
}
@When("the user clicks the login button")
public void userClicksLoginButton() {
driver.findElement(
By.cssSelector("button[type='submit']")).click();
}
@When("the user leaves the username field empty")
public void userLeavesUsernameEmpty() {
// Intentionally do nothing
}
@Then("the user should be redirected to the dashboard")
public void userRedirectedToDashboard() {
wait.until(ExpectedConditions.urlContains("/dashboard"));
Assert.assertTrue(
driver.getCurrentUrl().contains("/dashboard"),
"Should be on dashboard after login");
}
@Then("the welcome message should contain {string}")
public void welcomeMessageContains(String expectedText) {
WebElement welcome = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("welcome-message")));
Assert.assertTrue(
welcome.getText().contains(expectedText),
"Welcome message should contain: " + expectedText);
}
@Then("an error message {string} should be displayed")
public void errorMessageDisplayed(String expectedError) {
WebElement error = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".error-message")));
Assert.assertEquals(error.getText(), expectedError);
}
}# Run all Cucumber tests
mvn test
# Run only @smoke tests
mvn test -Dcucumber.filter.tags="@smoke"
# Dry run — check if all steps have definitions
mvn test -Dcucumber.execution.dry-run=trueThe most common error: "Undefined step." This means Cucumber cannot find a matching step definition. Check three things: (1) the glue path in @CucumberOptions includes the package with your step definitions, (2) the step text in the feature file exactly matches the annotation text, (3) you imported from io.cucumber.java.en, not from some other package.
When you write a new feature file, run with dryRun = true first. Cucumber will print the exact Java method signatures you need to create. Copy-paste them into your step definition class, add the implementation, and run again with dryRun = false.
Key Point: Feature file → step definitions → Cucumber matches text → Java code executes. Use dryRun to check mappings.