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