Skip to main content
TestContext is a plain Java class that acts as the shared state container for a single Cucumber scenario. It holds the WebDriver instance and is passed automatically between Hooks, step definition classes, and page objects via PicoContainer’s constructor injection.

Source

package utilities;

import org.openqa.selenium.WebDriver;

public class TestContext {
    public WebDriver driver;
}

Purpose

Cucumber runs each scenario in isolation, but multiple step definition classes (and the Hooks class) need to share the same browser session. TestContext solves this by providing a single object that PicoContainer creates once per scenario and injects wherever it is requested.
Scenario starts
    └─ PicoContainer creates TestContext
            ├─ Hooks(TestContext)    → @Before sets context.driver = new ChromeDriver()
            └─ RiuSteps(TestContext) → passes context.driver to RiuHome / LoginModal page objects

Fields

driver
WebDriver
The active Selenium WebDriver session for the current scenario. Set by Hooks.setUp() before any step runs, and nulled out implicitly when PicoContainer disposes the context after Hooks.tearDown() closes the browser.

How PicoContainer injection works

PicoContainer automatically manages TestContext because it is listed in the glue packages (steps and hooks). Any class in those packages that declares a constructor accepting TestContext will receive the same instance for the duration of a scenario.
// The actual step definition class in this project
public class RiuSteps {

    private TestContext context;
    private RiuHome riuHome;
    private LoginModal loginModal;

    public RiuSteps(TestContext context) {
        this.context = context;  // PicoContainer injects TestContext here
    }

    @Given("que el usuario navega a la pagina principal de RIU")
    public void navegarARiu() {
        riuHome = new RiuHome(context.driver);  // driver set by Hooks.setUp()
        riuHome.navigateToRiu();
    }

    @And("completa el formulario de registro sin fechas")
    public void completaElFormularioDeRegistro() {
        loginModal = new LoginModal(context.driver);  // same browser session
        loginModal.clickRegisterTab();
        loginModal.typeName("Fernando");
        // ...
    }
}
PicoContainer requires that injectable classes have a no-arg constructor or a single constructor that PicoContainer can satisfy. TestContext has the implicit no-arg constructor generated by the Java compiler, which is exactly what PicoContainer needs to instantiate it first.

Usage pattern in hooks

Hooks receives TestContext via its constructor and assigns the WebDriver to context.driver in @Before:
public Hooks(TestContext context) {
    this.context = context;
}

@Before
public void setUp() {
    context.driver = new ChromeDriver();
    context.driver.manage().window().maximize();
}

Extending TestContext

If you need to share additional state across step classes — for example, a test data object or a scenario name for screenshots — add public fields to TestContext:
public class TestContext {
    public WebDriver driver;
    public String scenarioName;  // populated in @Before from Scenario object
    public UserData testUser;    // populated by a step before it is needed
}
Keep TestContext fields simple and scenario-scoped. Do not store data that should persist across scenarios — PicoContainer creates a fresh instance for every scenario.

Build docs developers (and LLMs) love