Answer
API + UI Hybrid Cucumber Testing
Why Hybrid Testing?
CODE
API setup (0.2s) + UI verification (5s) = 5.2s per test
vs
UI setup (30s) + UI verification (5s) = 35s per test
Hybrid is 6x faster and more stable because:
- API calls don''t depend on UI rendering
- UI test focuses only on what matters: the display
- Faster feedback on UI bugs specifically
Feature File
Gherkin
@regression @hybrid
Feature: User Management (Admin Portal)
Scenario: Newly created user appears in admin user list
Given a user is created via API with role "MANAGER"
When the admin navigates to the user management page
And the admin searches for the created user
Then the user should appear with role "MANAGER"
And the user status should show "Active"
Scenario: Deleted user no longer appears in UI
Given a user is created via API with role "USER"
When the admin deletes the user via API
And the admin refreshes the user management page
Then the user should not appear in the list
Scenario: Product created via API is visible in storefront
Given a product is created via API:
| name | Wireless Headphones |
| price | 89.99 |
| category | Electronics |
| status | active |
When the customer navigates to the Electronics category
And the customer searches for "Wireless Headphones"
Then the product should appear with price "$89.99"
ScenarioContext — Shared Between API and UI Steps
Java
public class ScenarioContext {
// Shared state
public WebDriver driver;
public String createdUserId;
public String createdUserEmail;
public String createdProductId;
public SoftAssert softAssert = new SoftAssert();
}
API Step Definitions
Java
public class ApiSteps {
private final ScenarioContext ctx;
public ApiSteps(ScenarioContext ctx) { this.ctx = ctx; }
@Given("a user is created via API with role {string}")
public void createUserViaApi(String role) {
ctx.createdUserEmail = "test-" + System.currentTimeMillis() + "@qa.com";
Response resp = given()
.header("Authorization", "Bearer " + getAdminToken())
.contentType("application/json")
.body(Map.of(
"email", ctx.createdUserEmail,
"role", role,
"name", "QA Test User"
))
.post(ConfigReader.getApiUrl() + "/admin/users");
assertEquals(201, resp.statusCode());
ctx.createdUserId = resp.jsonPath().getString("id");
System.out.println("Created user: " + ctx.createdUserId);
}
@When("the admin deletes the user via API")
public void deleteUserViaApi() {
given()
.header("Authorization", "Bearer " + getAdminToken())
.delete(ConfigReader.getApiUrl() + "/admin/users/" + ctx.createdUserId)
.then().statusCode(200);
}
}
UI Step Definitions
Java
public class AdminUserSteps {
private final ScenarioContext ctx;
public AdminUserSteps(ScenarioContext ctx) { this.ctx = ctx; }
@When("the admin navigates to the user management page")
public void navigateToUserManagement() {
ctx.driver.get(ConfigReader.getBaseUrl() + "/admin/users");
}
@When("the admin searches for the created user")
public void searchForCreatedUser() {
ctx.adminPage.searchUser(ctx.createdUserEmail); // use email from API step
}
@Then("the user should appear with role {string}")
public void verifyUserRole(String expectedRole) {
ctx.softAssert.assertEquals(
ctx.adminPage.getUserRole(ctx.createdUserEmail),
expectedRole, "Role mismatch");
}
@Then("the user should not appear in the list")
public void verifyUserDeleted() {
ctx.softAssert.assertFalse(
ctx.adminPage.isUserVisible(ctx.createdUserEmail),
"Deleted user still visible");
}
}
Cleanup Hook
Java
@After("@hybrid")
public void cleanupCreatedEntities() {
if (ctx.createdUserId != null) {
// API cleanup — faster than UI deletion
given()
.header("Authorization", "Bearer " + getAdminToken())
.delete(ConfigReader.getApiUrl() + "/admin/users/" + ctx.createdUserId);
ctx.createdUserId = null;
}
}
Test Execution Flow
CODE
@Before: Initialize WebDriver + API client
@Given (API): Create user via REST API (0.2s)
@When (UI): Navigate to admin page, search user (3s)
@Then (UI): Verify user appears correctly (1s)
@After cleanup: Delete user via API (0.1s)
Total: ~4.5 seconds vs 35s for full UI test
