Intermediate
Chapter 11 · 10 min read
Sharing State & Dependency Injection
Share WebDriver and test data across step definition classes using PicoContainer (Java) and Behave's context (Python).
Sharing State Across Steps
Scenarios often span multiple step definition classes — login steps, navigation steps, verification steps. They all need access to the same WebDriver and test data. Dependency injection solves this cleanly.
pom-picocontainer.xml
<!-- Add to pom.xml for dependency injection -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<!-- PicoContainer automatically:
1. Creates one instance of each class per scenario
2. Injects constructor dependencies
3. Destroys instances after scenario ends
So if LoginSteps and CartSteps both need TestContext,
they get the SAME instance automatically. -->
CartSteps.java
package com.bdd.course.stepdefinitions;
import io.cucumber.java.en.*;
import com.bdd.course.context.TestContext;
import org.testng.Assert;
public class CartSteps {
// Same TestContext instance as LoginSteps — injected by PicoContainer
private final TestContext context;
public CartSteps(TestContext context) {
this.context = context;
}
@Given("the user is logged in as {string}")
public void userLoggedIn(String role) {
// Uses same driver from context
context.getDriver().get("https://example.com/login");
context.getLoginPage().loginAs(role, role + "123");
}
@When("the user adds {string} to the cart")
public void addToCart(String item) {
// Use same driver session — user is already logged in
System.out.println("Adding to cart: " + item);
}
@Then("the cart should contain {int} item(s)")
public void cartItemCount(int expectedCount) {
System.out.println("Cart items: " + expectedCount);
}
}
environment.py
# features/environment.py
# Behave's context object is the shared state container
from selenium import webdriver
from pages.login_page import LoginPage
def before_scenario(context, scenario):
context.driver = webdriver.Chrome()
context.driver.implicitly_wait(10)
context.driver.maximize_window()
# Pre-create page objects on context
context.login_page = LoginPage(context.driver)
# Shared test data
context.test_data = {}
def after_scenario(context, scenario):
if hasattr(context, 'driver'):
context.driver.quit()
cart_steps.py
# features/steps/cart_steps.py
from behave import given, when, then
@given('the user is logged in as "{role}"')
def step_logged_in(context, role):
# context.driver is shared across ALL step files
context.driver.get("https://example.com/login")
context.login_page.login_as(role, role + "123")
@when('the user adds "{item}" to the cart')
def step_add_to_cart(context, item):
# Same browser session — user is already logged in
print(f"Adding to cart: {item}")
# Store data for later steps
context.test_data['last_item'] = item
@then('the cart should contain {count:d} item')
def step_cart_count(context, count):
print(f"Cart items: {count}")
@then('the cart should contain {count:d} items')
def step_cart_count_plural(context, count):
print(f"Cart items: {count}")
# context is available in ALL step files automatically
# No need for imports or dependency injection
# Just use context.driver, context.test_data, etc.
Cucumber BDD
Intermediate
Sharing State & Dependency Injection
Written by PV
© 2026 All Rights Reserved