Advanced
Chapter 18 · 10 min read
Reusable Step Libraries
Build a library of generic, reusable step definitions — navigation steps, form steps, verification steps, and wait steps.
Building Reusable Step Libraries
As your BDD suite grows, you'll notice repeated patterns — navigating, clicking, verifying text. Instead of writing bespoke steps for every page, build a library of generic, composable steps.
CommonWebSteps.java
package com.bdd.course.stepdefinitions;
import io.cucumber.java.en.*;
import com.bdd.course.context.TestContext;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.*;
import org.testng.Assert;
import java.time.Duration;
public class CommonWebSteps {
private final TestContext ctx;
public CommonWebSteps(TestContext ctx) { this.ctx = ctx; }
// --- Navigation ---
@Given("the user navigates to {string}")
public void navigateTo(String url) {
ctx.getDriver().get(url);
}
@Given("the user is on the {string} page")
public void onPage(String pageName) {
// Map page names to URLs
String url = switch (pageName.toLowerCase()) {
case "login" -> "https://example.com/login";
case "home" -> "https://example.com/";
case "dashboard" -> "https://example.com/dashboard";
default -> throw new IllegalArgumentException("Unknown: " + pageName);
};
ctx.getDriver().get(url);
}
// --- Form interaction ---
@When("the user types {string} into the {string} field")
public void typeIntoField(String text, String fieldName) {
WebElement field = ctx.getDriver().findElement(By.name(fieldName));
field.clear();
field.sendKeys(text);
}
@When("the user clicks the {string} button")
public void clickButton(String buttonText) {
ctx.getDriver().findElement(
By.xpath("//button[contains(text(),'" + buttonText + "')]"))
.click();
}
@When("the user clicks the element with id {string}")
public void clickById(String id) {
ctx.getDriver().findElement(By.id(id)).click();
}
// --- Verification ---
@Then("the page title should be {string}")
public void verifyTitle(String expected) {
Assert.assertEquals(ctx.getDriver().getTitle(), expected);
}
@Then("the URL should contain {string}")
public void urlContains(String text) {
Assert.assertTrue(ctx.getDriver().getCurrentUrl().contains(text));
}
@Then("the element {string} should be visible")
public void elementVisible(String cssSelector) {
WebElement el = ctx.getDriver().findElement(By.cssSelector(cssSelector));
Assert.assertTrue(el.isDisplayed());
}
@Then("the text {string} should be visible on the page")
public void textVisible(String text) {
Assert.assertTrue(ctx.getDriver().getPageSource().contains(text));
}
// --- Waits ---
@When("the user waits for the element {string} to be visible")
public void waitForVisible(String css) {
new WebDriverWait(ctx.getDriver(), Duration.ofSeconds(10))
.until(ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(css)));
}
}
common_web_steps.py
# features/steps/common_web_steps.py
from behave import given, when, then
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
PAGE_MAP = {
'login': 'https://example.com/login',
'home': 'https://example.com/',
'dashboard': 'https://example.com/dashboard',
}
# --- Navigation ---
@given('the user navigates to "{url}"')
def step_navigate(context, url):
context.driver.get(url)
@given('the user is on the "{page_name}" page')
def step_on_page(context, page_name):
url = PAGE_MAP.get(page_name.lower())
if not url:
raise ValueError(f"Unknown page: {page_name}")
context.driver.get(url)
# --- Form ---
@when('the user types "{text}" into the "{field_name}" field')
def step_type(context, text, field_name):
el = context.driver.find_element(By.NAME, field_name)
el.clear()
el.send_keys(text)
@when('the user clicks the "{button_text}" button')
def step_click_button(context, button_text):
context.driver.find_element(
By.XPATH, f"//button[contains(text(),'{button_text}')]").click()
@when('the user clicks the element with id "{el_id}"')
def step_click_id(context, el_id):
context.driver.find_element(By.ID, el_id).click()
# --- Verification ---
@then('the page title should be "{expected}"')
def step_title(context, expected):
assert context.driver.title == expected
@then('the URL should contain "{text}"')
def step_url_contains(context, text):
assert text in context.driver.current_url
@then('the element "{css}" should be visible')
def step_element_visible(context, css):
el = context.driver.find_element(By.CSS_SELECTOR, css)
assert el.is_displayed()
@then('the text "{text}" should be visible on the page')
def step_text_visible(context, text):
assert text in context.driver.page_source
# --- Waits ---
@when('the user waits for the element "{css}" to be visible')
def step_wait_visible(context, css):
WebDriverWait(context.driver, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, css)))
Cucumber BDD
Advanced
Reusable Step Libraries
Written by PV
© 2026 All Rights Reserved