Skip to main content

Scenario & Suite Context

Selenium Boot provides two built-in context stores for sharing state between steps and tests without static fields or thread-unsafe globals.


ScenarioContext — In-Test State

Thread-local store that lives for the duration of a single test. Automatically cleared after each test.

In BaseTest / BaseApiTest

public class OrderTest extends BaseApiTest {

@Test
public void createAndVerifyOrder() {
// Step 1 — create order, store ID
ApiResponse res = ApiClient.post("/api/orders")
.body(Map.of("productId", 42))
.send()
.assertStatus(201);

ctx().set("orderId", res.json("$.orderId"));

// Step 2 — use stored ID in next call
String orderId = ctx().get("orderId");
ApiClient.get("/api/orders/" + orderId)
.send()
.assertStatus(200);
}
}

Typed retrieval

ctx().set("userId", 42);
int userId = ctx().get("userId", Integer.class);

Check and remove

boolean has = ctx().has("token");
ctx().remove("token");
ctx().clear(); // clear all entries (done automatically after each test)

SuiteContext — Cross-Test State

Backed by a ConcurrentHashMap — survives between tests for the entire suite run. Thread-safe for parallel execution.

Use this when one test creates a resource that later tests need.

public class ApiFlowTest extends BaseApiTest {

@Test(priority = 1)
public void createUser() {
ApiResponse res = ApiClient.post("/api/users")
.body(Map.of("name", "Alice"))
.send()
.assertStatus(201);

// Store for later tests
suiteCtx().set("createdUserId", res.json("$.id"));
}

@Test(priority = 2, dependsOnMethods = "createUser")
public void verifyUserExists() {
String userId = suiteCtx().get("createdUserId");

ApiClient.get("/api/users/" + userId)
.send()
.assertStatus(200)
.assertJson("$.name", "Alice");
}

@Test(priority = 3, dependsOnMethods = "createUser")
public void deleteUser() {
String userId = suiteCtx().get("createdUserId");

ApiClient.delete("/api/users/" + userId)
.send()
.assertStatus(204);
}
}

Methods

suiteCtx().set("key", value);
suiteCtx().get("key");
suiteCtx().get("key", Integer.class); // typed
suiteCtx().has("key");
suiteCtx().remove("key");
suiteCtx().clear();

Hybrid UI + API with Context

Share data between an API call and a browser step in the same test:

public class CheckoutTest extends BaseTest {

@Test
public void addItemAndVerifyCart() {
// API — add item to cart, store cart ID
ApiResponse cart = apiClient().post("/api/cart/items")
.body(Map.of("productId", 5, "qty", 2))
.send()
.assertStatus(200);

ctx().set("cartId", cart.json("$.cartId"));

// UI — open cart and verify
open("/cart/" + ctx().get("cartId"));
Assert.assertEquals(getText(By.cssSelector(".item-count")), "2 items");
}
}

When to Use Which

NeedUse
Pass data between steps in one testctx()ScenarioContext
Pass data from test A to test BsuiteCtx()SuiteContext
Share a created resource ID across the suitesuiteCtx()
Store a token for one test onlyctx()
Store a suite-wide auth tokenApiClient.setGlobalAuth()