πŸ’‘ If you like this website, please share it with your friends and network! πŸš€
Back to Home
πŸ₯’ Cucumber BDDβ˜• Selenium + JavaπŸ“¦ Maven

BDD Automation Interview Prep Track

Complete reference and practice dashboard for QA & SDET engineers β€” covering architecture, Gherkin syntax, Hooks, parallel execution, and structured answers to top scenario-based interview questions.

40Core Sections
20+Practical Codes
29Interview Targets
7Categories
0%
BDD Mastered0 of 40 Concepts
πŸ₯’
Overview⭐ Interview Focus#1

What is BDD Framework?

Behavior Driven Development with Gherkin syntax for human-readable test scenarios.

BDD (Behavior Driven Development) is an automation testing approach where test scenarios are written in plain English using Gherkin syntax β€” enabling developers, testers, business analysts, and product owners to collaboratively understand and validate application behavior without requiring technical expertise.

Key Core Points

  • βœ“Bridges the gap between technical and non-technical stakeholders.
  • βœ“Tests are written in plain English using Gherkin (Given / When / Then).
  • βœ“Each scenario represents a real business use case.
  • βœ“Step definitions translate English statements into executable Java code.
  • βœ“Cucumber is the most widely adopted BDD framework for Java projects.

Technologies / Packages

SeleniumJavaCucumberMavenTestNG / JUnitGherkin

Core Framework Benefits

  • β†’Better readability for all team members.
  • β†’Faster onboarding for new QA engineers.
  • β†’Real-time understanding of application flow.
  • β†’Reusable automation framework components.
  • β†’Improved collaboration between Dev, QA, and Business.
πŸ—οΈ
Architecture⭐ Interview Focus#2

Framework Architecture

How the BDD automation project is structurally designed for scalability and reuse.

Framework architecture defines the structural blueprint of an automation project, governing how components interact, how tests are organized, and how the system scales as new features are added. A well-designed BDD architecture separates concerns cleanly β€” features from logic, configuration from execution.

Main Components

  • Feature Files β€” Business scenarios in Gherkin.
  • Step Definitions β€” Java binding for feature steps.
  • Page Object Model (POM) Classes β€” Element locators and actions.
  • Utility Classes β€” Reusable helper methods (Wait, Screenshot, Excel).
  • Hooks β€” Before/After execution lifecycle methods.
  • Runner Classes β€” Cucumber test execution configuration.
  • Reports β€” Extent/Allure test result dashboards.
  • Config Files β€” Environment and browser settings.

Core Framework Benefits

  • β†’Scalable β€” New tests added without structural changes.
  • β†’Reusable β€” Common methods used across the entire suite.
  • β†’Maintainable β€” Element changes are isolated to one page class.
  • β†’Debuggable β€” Clear separation makes failure isolation straightforward.
  • β†’Faster execution β€” Parallel test support by design.
πŸ“
Architecture#3

Project Structure

Standard Maven BDD project directory layout with folder responsibilities.

A well-organized project structure ensures that every team member can immediately navigate the codebase, locate test logic, and understand the purpose of each folder. The Maven standard directory layout separates main source from test resources cleanly.

Folder Responsibilities

  • base/ β€” Centralized driver initialization and teardown.
  • pages/ β€” Page classes with web elements and interaction methods.
  • stepdefinitions/ β€” Java methods bound to each Gherkin step.
  • hooks/ β€” Cross-cutting concerns: browser lifecycle, screenshots.
  • runners/ β€” @CucumberOptions configuration for test execution.
  • utilities/ β€” Shared helpers used across the entire project.
  • features/ β€” Plain-English test scenarios organized by module.
  • config/ β€” Externalized environment URLs, browser, credentials.
  • testdata/ β€” Parameterized test data for data-driven scenarios.
project-structure.txt
Project Structure
src/
β”œβ”€β”€ test/
β”‚   β”œβ”€β”€ java/
β”‚   β”‚   β”œβ”€β”€ base/            ← BaseTest class (driver setup)
β”‚   β”‚   β”œβ”€β”€ pages/           ← Page Object Model classes
β”‚   β”‚   β”œβ”€β”€ stepdefinitions/ ← Cucumber step bindings
β”‚   β”‚   β”œβ”€β”€ hooks/           ← @Before / @After lifecycle
β”‚   β”‚   β”œβ”€β”€ runners/         ← CucumberOptions runner class
β”‚   β”‚   └── utilities/       ← Screenshot, Wait, Excel helpers
β”‚   └── resources/
β”‚       β”œβ”€β”€ features/        ← .feature files (Gherkin scenarios)
β”‚       β”œβ”€β”€ config/          ← config.properties (env settings)
β”‚       └── testdata/        ← Excel / JSON test data files
πŸ“¦
Configuration#4

Maven Project Setup

Dependency management and build lifecycle configuration using pom.xml.

Maven orchestrates dependency resolution, build lifecycle management, and CI/CD integration for the BDD framework. All third-party libraries are declared in `pom.xml` β€” Maven automatically downloads and links them, eliminating manual JAR management.

pom.xml
XML / pom.xml
<!-- pom.xml β€” Core BDD Framework Dependencies -->
<dependencies>
  <!-- Selenium WebDriver -->
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.18.1</version>
  </dependency>

  <!-- Cucumber Java Bindings -->
  <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>7.15.0</version>
  </dependency>

  <!-- Cucumber TestNG Integration -->
  <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-testng</artifactId>
    <version>7.15.0</version>
  </dependency>

  <!-- WebDriverManager β€” Auto driver downloads -->
  <dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.7.0</version>
  </dependency>

  <!-- Apache POI β€” Excel data handling -->
  <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.5</version>
  </dependency>

  <!-- Log4j β€” Execution logging -->
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.23.1</version>
  </dependency>
</dependencies>

Core Framework Benefits

  • β†’Automatic dependency resolution β€” no manual JAR downloads.
  • β†’Centralized version management across all dependencies.
  • β†’Native CI/CD support via `mvn test` command.
  • β†’Plugin ecosystem for reporting (Surefire, Failsafe).
πŸ”§
Core Components⭐ Interview Focus#5

Base Class

Centralized browser initialization and teardown β€” the heart of the framework.

The Base class is the foundation of the entire framework. It centralizes WebDriver initialization, browser configuration, and teardown in a single reusable class, preventing code duplication across every test class.

BaseTest.java
Java
public class BaseTest {
    protected static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

    public static WebDriver getDriver() {
        return driver.get();
    }

    public void setup(String browser) {
        WebDriver webDriver;
        switch (browser.toLowerCase()) {
            case "firefox":
                WebDriverManager.firefoxdriver().setup();
                webDriver = new FirefoxDriver();
                break;
            case "edge":
                WebDriverManager.edgedriver().setup();
                webDriver = new EdgeDriver();
                break;
            default:
                WebDriverManager.chromedriver().setup();
                webDriver = new ChromeDriver();
        }
        webDriver.manage().window().maximize();
        webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        driver.set(webDriver);
    }

    public void tearDown() {
        if (getDriver() != null) {
            getDriver().quit();
            driver.remove(); // Important for thread safety in parallel runs
        }
    }
}

Core Framework Benefits

  • β†’Single location for browser setup β€” change once, applies everywhere.
  • β†’ThreadLocal driver ensures thread-safety for parallel execution.
  • β†’Centralized teardown prevents browser leaks.
  • β†’Easily extended for remote/grid execution.
🌐
Core Components#6

Driver Initialization & WebDriverManager

Automatic browser driver management β€” no manual driver downloads required.

WebDriverManager by Boni Garcia eliminates the manual overhead of downloading, versioning, and referencing browser drivers. It automatically detects the installed browser version and downloads the corresponding compatible driver at runtime.

DriverFactory.java
Java
// Old approach (manual) β€” AVOID in modern frameworks
System.setProperty("webdriver.chrome.driver", "drivers/chromedriver.exe");

// βœ… Modern approach β€” WebDriverManager handles everything
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();

// Firefox
WebDriverManager.firefoxdriver().setup();
WebDriver driver = new FirefoxDriver();

// Edge
WebDriverManager.edgedriver().setup();
WebDriver driver = new EdgeDriver();

// Headless Chrome (for CI/CD pipelines)
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless", "--no-sandbox", "--disable-dev-shm-usage");
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver(options);

Core Framework Benefits

  • β†’Zero manual driver file management.
  • β†’Automatically resolves version compatibility conflicts.
  • β†’Supports Chrome, Firefox, Edge, Opera, and remote drivers.
  • β†’Works seamlessly inside Docker CI/CD environments.
πŸ“„
Core Components⭐ Interview Focus#7

Page Object Model (POM)

Design pattern that separates UI element locators from test logic for maximum reusability.

The Page Object Model is a design pattern that encapsulates all web element locators and interaction methods for a given page within a dedicated Java class. This separation ensures that UI changes only require updates in a single class β€” not across dozens of test methods.

LoginPage.java
Java
// LoginPage.java
public class LoginPage extends BaseTest {

    // Element locators using @FindBy (PageFactory)
    @FindBy(id = "username")
    private WebElement usernameField;

    @FindBy(id = "password")
    private WebElement passwordField;

    @FindBy(css = "button[type='submit']")
    private WebElement loginButton;

    @FindBy(css = ".error-message")
    private WebElement errorMessage;

    // Constructor β€” initializes PageFactory
    public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    // Actions β€” clean, readable method names
    public void enterUsername(String username) {
        usernameField.clear();
        usernameField.sendKeys(username);
    }

    public void enterPassword(String password) {
        passwordField.clear();
        passwordField.sendKeys(password);
    }

    public void clickLogin() {
        loginButton.click();
    }

    public String getErrorMessage() {
        return errorMessage.getText();
    }

    // Chained method for fluent style
    public DashboardPage loginAs(String user, String pass) {
        enterUsername(user);
        enterPassword(pass);
        clickLogin();
        return new DashboardPage(getDriver());
    }
}

Core Framework Benefits

  • β†’UI changes require updates in only one class.
  • β†’Page methods are reused across multiple step definitions.
  • β†’Improves readability β€” `loginPage.clickLogin()` is self-documenting.
  • β†’PageFactory reduces boilerplate locator initialization.
πŸ“‹
Core Components⭐ Interview Focus#8

Feature File (Gherkin)

Human-readable test scenarios written in Gherkin β€” the living documentation of the system.

Feature files are the face of BDD β€” plain English specifications written in Gherkin syntax that describe business behavior. They serve as both executable test specifications and living documentation that any stakeholder can read and validate.

Gherkin Keywords

  • Feature β€” High-level description of the functionality being tested.
  • Background β€” Steps that run before every scenario in the feature.
  • Scenario β€” A single, specific test case.
  • Scenario Outline β€” Parameterized scenario executed with multiple data rows.
  • Given β€” Precondition or initial state.
  • When β€” The action taken by the user.
  • Then β€” The expected outcome/assertion.
  • And β€” Continuation of Given / When / Then.
  • Examples β€” Data table for Scenario Outline parameterization.
  • @tags β€” Organize and filter which scenarios to execute.
Login.feature
Gherkin
# src/test/resources/features/Login.feature
Feature: Login Functionality
  As a registered user
  I want to login to the application
  So that I can access my account

  Background:
    Given the application is launched on "chrome"
    And the user navigates to the login page

  @smoke @regression
  Scenario: Successful login with valid credentials
    When the user enters username "admin@example.com"
    And the user enters password "Admin@123"
    And the user clicks the login button
    Then the user should be redirected to the Dashboard
    And the welcome message should display "Welcome, Admin"

  @negative
  Scenario: Login fails with invalid password
    When the user enters username "admin@example.com"
    And the user enters password "wrongpassword"
    And the user clicks the login button
    Then the error message "Invalid credentials" should be displayed

  @datadriven
  Scenario Outline: Login with multiple user types
    When the user enters username "<username>"
    And the user enters password "<password>"
    And the user clicks the login button
    Then the dashboard heading "<heading>" should be visible

    Examples:
      | username          | password   | heading        |
      | admin@test.com    | Admin@123  | Admin Panel    |
      | manager@test.com  | Mgr@456    | Manager View   |
      | user@test.com     | User@789   | User Dashboard |
πŸ”—
Core Components⭐ Interview Focus#9

Step Definition File

Java methods bound to each Gherkin step β€” the bridge between English and code.

Step definition files are the technical implementation layer of BDD. Each Gherkin step in a feature file is matched to a Java method annotated with `@Given`, `@When`, or `@Then`. Cucumber uses regex or Cucumber Expressions to match the step text to the corresponding method.

LoginSteps.java
Java
// LoginSteps.java
public class LoginSteps {

    private LoginPage loginPage;
    private DashboardPage dashboardPage;

    @Given("the application is launched on {string}")
    public void theApplicationIsLaunched(String browser) {
        BaseTest.setup(browser);
        loginPage = new LoginPage(BaseTest.getDriver());
    }

    @Given("the user navigates to the login page")
    public void theUserNavigatesToLoginPage() {
        String url = ConfigReader.get("url");
        BaseTest.getDriver().get(url);
    }

    @When("the user enters username {string}")
    public void theUserEntersUsername(String username) {
        loginPage.enterUsername(username);
    }

    @When("the user enters password {string}")
    public void theUserEntersPassword(String password) {
        loginPage.enterPassword(password);
    }

    @When("the user clicks the login button")
    public void theUserClicksLoginButton() {
        dashboardPage = loginPage.clickLogin();
    }

    @Then("the user should be redirected to the Dashboard")
    public void theUserShouldBeRedirectedToDashboard() {
        Assert.assertTrue(
            dashboardPage.isLoaded(),
            "Dashboard was not loaded after login."
        );
    }

    @Then("the error message {string} should be displayed")
    public void theErrorMessageShouldBeDisplayed(String expectedMsg) {
        String actual = loginPage.getErrorMessage();
        Assert.assertEquals(actual, expectedMsg,
            "Error message mismatch.");
    }
}

Core Framework Benefits

  • β†’Clean separation β€” English in feature files, Java in step definitions.
  • β†’Same step text can be reused across multiple feature files.
  • β†’Cucumber Expressions (`{string}`, `{int}`) extract parameters automatically.
  • β†’Regex patterns enable flexible step matching.
▢️
Core Components⭐ Interview Focus#10

Runner File

The test execution orchestrator that wires feature files to step definitions.

The Runner class configures and triggers Cucumber test execution. It uses `@CucumberOptions` to define where feature files and step definitions are located, which tags to include or exclude, and which reporting plugins to activate.

Key @CucumberOptions Parameters

  • features β€” Path to the .feature files directory.
  • glue β€” Package path to step definitions and hooks.
  • tags β€” Filter which scenarios to run (@smoke, @regression, ~@skip).
  • plugin β€” Reporting output formats (HTML, JSON, JUnit, Allure).
  • dryRun β€” Validate step bindings exist without executing tests.
  • monochrome β€” Clean console output (removes ANSI escape codes).
TestRunner.java
Java
// TestRunner.java
@RunWith(Cucumber.class)
@CucumberOptions(
    // Path to .feature files
    features = "src/test/resources/features",

    // Package containing step definition classes
    glue = {"stepdefinitions", "hooks"},

    // Tag filtering β€” run specific tagged scenarios
    tags = "@smoke",

    // Reporting plugins
    plugin = {
        "pretty",                                     // Console formatting
        "html:target/cucumber-reports/report.html",   // HTML report
        "json:target/cucumber-reports/report.json",   // JSON for Extent/Allure
        "junit:target/cucumber-reports/report.xml",   // JUnit for Jenkins
        "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"  // Allure
    },

    // Publish to Cucumber cloud report
    publish = false,

    // Print step snippets for unimplemented steps
    snippets = SnippetType.CAMELCASE,

    // Show or suppress @tags in reports
    dryRun = false,
    monochrome = true
)
public class TestRunner extends AbstractTestNGCucumberTests {

    // Override for parallel execution support
    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }
}
πŸͺ
Core Components⭐ Interview Focus#11

Hooks in Cucumber

@Before and @After methods that manage browser lifecycle and test setup/teardown.

Hooks are Cucumber lifecycle methods that execute before and after each scenario (or entire test suite). They are the ideal place to manage browser initialization, environment setup, screenshot capture on failure, and cleanup operations.

Hook Types

  • @Before β€” Runs before each scenario (browser launch, navigation).
  • @After β€” Runs after each scenario (screenshot, browser close).
  • @BeforeAll β€” Runs once before all scenarios in the suite.
  • @AfterAll β€” Runs once after all scenarios complete.
  • @Before("@tagName") β€” Conditional hook for specific tagged scenarios.
  • order parameter β€” Controls execution order when multiple hooks exist.
Hooks.java
Java
// Hooks.java
public class Hooks extends BaseTest {

    private final Scenario scenario;

    // Cucumber injects the Scenario object automatically
    public Hooks(Scenario scenario) {
        this.scenario = scenario;
    }

    @Before(order = 1)
    public void beforeScenario() {
        // Read browser from config file
        String browser = ConfigReader.get("browser");
        setup(browser); // Launch browser from BaseTest

        // Navigate to application URL
        getDriver().get(ConfigReader.get("url"));

        LogManager.getLogger().info(
            "β–Ά Starting Scenario: " + scenario.getName()
        );
    }

    @After(order = 1)
    public void afterScenario() {
        // Capture screenshot on failure
        if (scenario.isFailed()) {
            byte[] screenshot = ((TakesScreenshot) getDriver())
                .getScreenshotAs(OutputType.BYTES);
            scenario.attach(screenshot, "image/png", "Failure Screenshot");

            LogManager.getLogger().error(
                "❌ Scenario FAILED: " + scenario.getName()
            );
        }

        // Always close the browser
        tearDown();
    }

    // Tagged hooks β€” only run for specific tags
    @Before("@clearCookies")
    public void clearCookies() {
        getDriver().manage().deleteAllCookies();
    }
}
πŸ› οΈ
Core Components#12

Utility Classes

Reusable helper methods shared across the entire framework.

Utility classes encapsulate cross-cutting concerns like wait management, screenshot capture, JavaScript execution, Excel data reading, and property file parsing. By centralizing these capabilities, all step definitions and page classes can use them without code duplication.

Common Utility Classes

  • WaitUtility β€” Explicit, fluent wait wrappers.
  • ScreenshotUtility β€” Capture screenshots as bytes or files.
  • ExcelUtility β€” Read/write test data using Apache POI.
  • JavaScriptUtility β€” Execute JS: scroll, click, highlight.
  • ConfigReader β€” Parse config.properties into key-value pairs.
  • LogUtility β€” Structured Log4j logger wrapper.
WaitUtility.java
Java
// WaitUtility.java
public class WaitUtility {

    // Explicit wait β€” waits for a specific condition
    public static WebElement waitForVisible(By locator, int seconds) {
        WebDriverWait wait = new WebDriverWait(
            BaseTest.getDriver(), Duration.ofSeconds(seconds)
        );
        return wait.until(
            ExpectedConditions.visibilityOfElementLocated(locator)
        );
    }

    public static boolean waitForInvisible(By locator, int seconds) {
        WebDriverWait wait = new WebDriverWait(
            BaseTest.getDriver(), Duration.ofSeconds(seconds)
        );
        return wait.until(
            ExpectedConditions.invisibilityOfElementLocated(locator)
        );
    }

    public static WebElement waitForClickable(By locator, int seconds) {
        WebDriverWait wait = new WebDriverWait(
            BaseTest.getDriver(), Duration.ofSeconds(seconds)
        );
        return wait.until(
            ExpectedConditions.elementToBeClickable(locator)
        );
    }
}

// ScreenshotUtility.java
public class ScreenshotUtility {

    public static byte[] captureAsBytes(WebDriver driver) {
        return ((TakesScreenshot) driver)
            .getScreenshotAs(OutputType.BYTES);
    }

    public static void saveToFile(WebDriver driver, String fileName) {
        File src = ((TakesScreenshot) driver)
            .getScreenshotAs(OutputType.FILE);
        try {
            FileUtils.copyFile(src,
                new File("target/screenshots/" + fileName + ".png")
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
⏳
Configuration⭐ Interview Focus#13

Wait Handling

Synchronization strategies to handle dynamic web elements gracefully.

Wait handling is one of the most critical aspects of stable automation. Improper waits are the primary cause of flaky tests. BDD frameworks should exclusively use Explicit Waits for targeted synchronization.

Wait Types Comparison

  • Implicit Wait β€” Global wait applied to all findElement calls. Can mask timing issues. Not recommended.
  • Explicit Wait β€” Targeted wait for a specific element/condition. Best practice.
  • Fluent Wait β€” Customizable polling interval, exception handling. Used for complex timing scenarios.
  • Thread.sleep() β€” Hard-coded pause. Never use in production frameworks.
WaitExamples.java
Java
// ❌ NEVER use Thread.sleep β€” wastes time unconditionally
Thread.sleep(3000); // Freezes for 3 seconds regardless of element state

// ❌ AVOID Implicit Wait β€” applies globally, masks real timing issues
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

// βœ… BEST: Explicit Wait β€” waits only until condition is met
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));

// Wait for element to be visible
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dashboard")));

// Wait for text to appear
wait.until(ExpectedConditions.textToBePresentInElement(heading, "Welcome"));

// Wait for URL to change
wait.until(ExpectedConditions.urlContains("/dashboard"));

// βœ… Fluent Wait β€” custom polling interval + exception ignore
Wait<WebDriver> fluentWait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofMillis(500))
    .ignoring(NoSuchElementException.class)
    .withMessage("Element not found after 30 seconds");

fluentWait.until(d -> d.findElement(By.id("loader")).isDisplayed() == false);
βš™οΈ
Configuration#14

Config File Handling

Externalize environment settings with config.properties for zero hardcoding.

Config files store environment-specific data like browser type, application URLs, credentials, and timeout values outside the code. This enables switching between environments (dev, staging, production) by modifying a single file without touching Java source.

ConfigReader.java
Java
# src/test/resources/config/config.properties
browser=chrome
url=https://staging.example.com
username=admin@example.com
password=Admin@123
timeout=15
headless=false

---

// ConfigReader.java β€” Reads config.properties at runtime
public class ConfigReader {
    private static Properties properties;

    static {
        try {
            FileInputStream fis = new FileInputStream(
                "src/test/resources/config/config.properties"
            );
            properties = new Properties();
            properties.load(fis);
        } catch (IOException e) {
            throw new RuntimeException("Cannot load config.properties", e);
        }
    }

    public static String get(String key) {
        String value = properties.getProperty(key);
        if (value == null) {
            throw new RuntimeException("Key '" + key + "' not found in config.");
        }
        return value.trim();
    }

    public static int getInt(String key) {
        return Integer.parseInt(get(key));
    }

    public static boolean getBoolean(String key) {
        return Boolean.parseBoolean(get(key));
    }
}

Core Framework Benefits

  • β†’No hardcoded URLs, credentials, or browser names in test code.
  • β†’Switch environments by changing one line in config.properties.
  • β†’CI/CD pipelines can override values via system properties.
  • β†’Protects sensitive data from being embedded in source code.
πŸ“Š
Test Data & Reporting#15

Test Data Handling

Data-driven testing using Excel (Apache POI), JSON, and Scenario Outline.

Test data management enables running the same test logic across multiple data sets. BDD frameworks commonly use Scenario Outline with Examples tables for inline data, or Apache POI for reading external Excel sheets for complex data-driven scenarios.

Data Sources Supported

  • Scenario Outline + Examples β€” Best for simple tabular data in feature files.
  • Excel (.xlsx) via Apache POI β€” Industry standard for complex datasets.
  • JSON files β€” Ideal for API test payloads and nested data structures.
  • config.properties β€” For static environment configuration values.
  • CSV files β€” Lightweight alternative to Excel for flat data.
ExcelUtility.java
Java
// ExcelUtility.java β€” Read data from Excel using Apache POI
public class ExcelUtility {

    public static String getCellData(String filePath, String sheetName,
                                      int row, int col) throws Exception {
        FileInputStream fis = new FileInputStream(filePath);
        Workbook workbook = WorkbookFactory.create(fis);
        Sheet sheet = workbook.getSheet(sheetName);
        Row excelRow = sheet.getRow(row);
        Cell cell = excelRow.getCell(col);
        workbook.close();
        return cell.toString();
    }

    public static List<Map<String, String>> getAllRows(String filePath,
                                                        String sheetName)
            throws Exception {
        FileInputStream fis = new FileInputStream(filePath);
        Workbook workbook = WorkbookFactory.create(fis);
        Sheet sheet = workbook.getSheet(sheetName);
        List<Map<String, String>> data = new ArrayList<>();
        Row header = sheet.getRow(0);

        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            Map<String, String> rowData = new LinkedHashMap<>();
            for (int j = 0; j < header.getLastCellNum(); j++) {
                rowData.put(
                    header.getCell(j).toString(),
                    row.getCell(j).toString()
                );
            }
            data.add(rowData);
        }
        workbook.close();
        return data;
    }
}
πŸ“ˆ
Test Data & Reporting⭐ Interview Focus#16

Reporting β€” Extent & Allure

Rich HTML dashboards with pass/fail metrics, screenshots, and execution trends.

Test reports communicate execution results to the entire team β€” developers, managers, and business stakeholders. Modern BDD frameworks use Extent Report or Allure Report to generate visually rich, interactive dashboards with embedded screenshots, step-level logs, and historical trend data.

Report Types

  • Extent Report β€” Rich HTML dashboard with charts, logs, and screenshot thumbnails.
  • Allure Report β€” Interactive timeline view with step-level details and trend graphs.
  • Cucumber HTML Report β€” Built-in basic HTML report from Cucumber plugin.
  • JUnit XML Report β€” Machine-readable format for Jenkins integration.
  • JSON Report β€” Raw data format consumed by Allure and Extent parsers.
ExtentReportManager.java
Java
// ExtentReportManager.java β€” Singleton pattern for thread-safe reporting
public class ExtentReportManager {
    private static ExtentReports extent;

    public static ExtentReports getInstance() {
        if (extent == null) {
            ExtentSparkReporter spark = new ExtentSparkReporter(
                "target/reports/ExtentReport.html"
            );
            spark.config().setTheme(Theme.DARK);
            spark.config().setDocumentTitle("BDD Automation Report");
            spark.config().setReportName("Regression Suite Results");

            extent = new ExtentReports();
            extent.attachReporter(spark);
            extent.setSystemInfo("Environment", "Staging");
            extent.setSystemInfo("Browser", ConfigReader.get("browser"));
            extent.setSystemInfo("OS", System.getProperty("os.name"));
        }
        return extent;
    }
}

// Usage inside Hooks.java
@After
public void afterScenario(Scenario scenario) {
    ExtentTest test = ExtentReportManager.getInstance()
        .createTest(scenario.getName());

    if (scenario.isFailed()) {
        test.fail("Scenario failed β€” attaching screenshot.")
            .addScreenCaptureFromBase64String(
                ScreenshotUtility.captureAsBase64(getDriver())
            );
    } else {
        test.pass("Scenario passed successfully.");
    }

    ExtentReportManager.getInstance().flush();
}
πŸ“Έ
Test Data & Reporting#17

Screenshot Capture on Failure

Automatic visual evidence collection on scenario failure for rapid defect analysis.

Screenshots captured at the moment of failure provide the single most effective tool for debugging flaky or intermittently failing tests. In BDD frameworks, screenshots are captured inside `@After` hooks and attached directly to the Cucumber Scenario object so they appear in every report format.

ScreenshotHook.java
Java
// Full screenshot strategy in Hooks.java
@After
public void captureFailureScreenshot(Scenario scenario) {
    if (scenario.isFailed()) {

        // Method 1: Attach to Cucumber Scenario (shows in all reports)
        byte[] screenshot = ((TakesScreenshot) getDriver())
            .getScreenshotAs(OutputType.BYTES);
        scenario.attach(screenshot, "image/png",
            "Failure: " + scenario.getName());

        // Method 2: Save to disk with timestamp
        String timestamp = LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
        String fileName = scenario.getName().replaceAll("\s+", "_")
            + "_" + timestamp;
        ScreenshotUtility.saveToFile(getDriver(), fileName);

        // Method 3: Log failure details
        LogManager.getLogger().error(
            "❌ FAILED: " + scenario.getName() +
            " | Tags: " + scenario.getSourceTagNames()
        );
    }
}

Core Framework Benefits

  • β†’Immediate visual context for every failed scenario.
  • β†’Timestamps prevent screenshots from overwriting each other.
  • β†’Embedding in Cucumber Scenario ensures screenshots appear in all report formats.
  • β†’Eliminates the need to reproduce failures manually.
πŸ“
Test Data & Reporting#18

Logging with Log4j

Structured execution logging for debugging, monitoring, and audit trails.

Log4j provides structured, levelled logging throughout the automation framework. Logs capture the sequence of actions, driver states, configuration values, and error details β€” forming a complete audit trail that accelerates failure diagnosis.

log4j2.xml
XML / pom.xml
# log4j2.xml β€” Log4j2 configuration
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <!-- Console output -->
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout
        pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
    <!-- File output -->
    <File name="LogFile" fileName="target/logs/automation.log" append="false">
      <PatternLayout
        pattern="%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger - %msg%n"/>
    </File>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Console"/>
      <AppenderRef ref="LogFile"/>
    </Root>
  </Loggers>
</Configuration>

---

// Usage in Java classes
private static final Logger logger = LogManager.getLogger(LoginSteps.class);

logger.info("β–Ά Navigating to login page: " + url);
logger.debug("Username field located: " + element.isDisplayed());
logger.warn("⚠ Element took longer than expected to load.");
logger.error("❌ Login failed β€” element not found: " + e.getMessage());

Core Framework Benefits

  • β†’INFO level logs show normal execution flow.
  • β†’ERROR level logs instantly highlight failure points.
  • β†’Log files persist after browser sessions close β€” critical for CI/CD.
  • β†’Supports log rotation, file appending, and multiple output targets.
🌍
Execution & CI/CD#19

Cross-Browser Testing

Execute the same test suite across Chrome, Firefox, and Edge with zero code changes.

Cross-browser testing validates that the application behaves identically across all supported browsers. The BDD framework achieves this by reading the target browser from `config.properties`, enabling browser switching without modifying any test code.

CrossBrowserSetup.java
Java
// config.properties β€” Single line change to switch browser
browser=firefox   # Change to: chrome | firefox | edge

// BaseTest.java β€” Dynamic browser resolution
public void setup(String browser) {
    WebDriver webDriver = switch (browser.toLowerCase()) {
        case "firefox" -> {
            WebDriverManager.firefoxdriver().setup();
            yield new FirefoxDriver();
        }
        case "edge" -> {
            WebDriverManager.edgedriver().setup();
            EdgeOptions options = new EdgeOptions();
            yield new EdgeDriver(options);
        }
        default -> {  // chrome
            WebDriverManager.chromedriver().setup();
            ChromeOptions options = new ChromeOptions();
            yield new ChromeDriver(options);
        }
    };
    webDriver.manage().window().maximize();
    driver.set(webDriver);
}

// Maven command β€” override browser at runtime
mvn test -Dbrowser=firefox -Denv=staging

Core Framework Benefits

  • β†’Browser flexibility without any code changes.
  • β†’CI/CD pipelines can pass `-Dbrowser` as a system property.
  • β†’WebDriverManager eliminates driver version conflicts across browsers.
⚑
Execution & CI/CD⭐ Interview Focus#20

Parallel Execution

Run multiple scenarios simultaneously using ThreadLocal driver and TestNG parallel mode.

Parallel execution dramatically reduces total suite runtime by running multiple scenarios simultaneously across independent browser threads. ThreadLocal WebDriver management is essential β€” it ensures each thread has its own isolated driver instance, preventing cross-thread interference.

ParallelExecution.java
Java
// TestRunner.java β€” Enable parallel execution
@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = {"stepdefinitions", "hooks"},
    plugin = {"pretty", "html:target/cucumber-reports/report.html"},
    tags = "@regression"
)
public class TestRunner extends AbstractTestNGCucumberTests {

    // This override enables parallel scenario execution
    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }
}

---

<!-- testng.xml β€” Configure thread count -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="BDD Regression Suite" parallel="methods" thread-count="4"
       verbose="1" data-provider-thread-count="4">
  <test name="Parallel BDD Tests">
    <classes>
      <class name="runners.TestRunner"/>
    </classes>
  </test>
</suite>

---

// Maven command for parallel execution
mvn test -Dthreads=4

Core Framework Benefits

  • β†’4 parallel threads can reduce a 40-minute suite to under 12 minutes.
  • β†’ThreadLocal driver ensures complete test isolation.
  • β†’Thread-count is configurable at runtime β€” no code changes needed.
  • β†’Maximizes CI/CD pipeline efficiency.
πŸ”
Execution & CI/CD⭐ Interview Focus#21

Jenkins CI/CD Integration

Automated test triggering, scheduling, and reporting inside Jenkins pipelines.

Jenkins automates the entire QA execution lifecycle β€” detecting code commits, triggering test suites, generating reports, and notifying the team of failures. The BDD framework integrates natively via Maven commands and JUnit XML report publishing.

Jenkins Integration Flow

  • 1. Developer pushes code to Git β†’ Webhook triggers Jenkins.
  • 2. Jenkins pulls latest code from repository.
  • 3. Maven resolves dependencies and compiles project.
  • 4. BDD suite executes with specified tags and browser.
  • 5. JUnit XML reports published to Jenkins test results.
  • 6. Allure/Extent HTML reports archived as build artifacts.
  • 7. Email/Slack notifications sent on failure.
Jenkinsfile
Groovy / Jenkinsfile
// Jenkinsfile β€” Declarative Pipeline for BDD automation
pipeline {
    agent any

    environment {
        BROWSER = 'chrome'
        ENV = 'staging'
    }

    stages {
        stage('Checkout Code') {
            steps {
                git branch: 'main',
                    url: 'https://github.com/org/bdd-automation.git'
            }
        }

        stage('Build & Install Dependencies') {
            steps {
                sh 'mvn clean install -DskipTests'
            }
        }

        stage('Run BDD Regression Suite') {
            steps {
                sh """
                    mvn test \
                        -Dbrowser=${BROWSER} \
                        -Denv=${ENV} \
                        -Dcucumber.filter.tags=@regression \
                        -Dthreads=4
                """
            }
        }

        stage('Publish Test Reports') {
            steps {
                // Publish JUnit XML results
                junit 'target/cucumber-reports/*.xml'
                // Publish Allure report
                allure includeProperties: false,
                       jdk: '',
                       results: [[path: 'target/allure-results']]
            }
        }
    }

    post {
        failure {
            emailext(
                subject: '❌ BDD Suite FAILED: ${BUILD_NUMBER}',
                body: 'Tests failed. See: ${BUILD_URL}',
                to: 'qa-team@company.com'
            )
        }
        always {
            cleanWs()
        }
    }
}
πŸ”€
Execution & CI/CD#22

Git Integration

Version-controlled automation code with collaborative branching workflows.

Git ensures that automation code is version-controlled, enabling collaborative development, rollback capability, and audit history. All framework files β€” feature files, step definitions, page classes, and configuration β€” must be committed to Git alongside the application source code.

git-commands.sh
Bash / Shell
# Git workflow for automation teams

# Initial setup β€” clone the automation repository
git clone https://github.com/org/bdd-automation.git
cd bdd-automation

# Create a feature branch for new test work
git checkout -b feature/JIRA-123-login-automation

# Stage and commit your changes
git add src/test/resources/features/Login.feature
git add src/test/java/stepdefinitions/LoginSteps.java
git add src/test/java/pages/LoginPage.java

git commit -m "feat(JIRA-123): Add BDD login automation with edge case coverage"

# Push to remote repository
git push origin feature/JIRA-123-login-automation

# Keep your branch up to date with main
git fetch origin
git rebase origin/main

# Merge via pull request (never commit directly to main)

# Useful commands
git log --oneline -10           # Last 10 commits
git diff main..HEAD             # Changes vs main branch
git stash                       # Temporarily save uncommitted work
git tag v1.0.0-regression       # Tag a stable suite version

Core Framework Benefits

  • β†’Full history of every test change β€” who, what, and when.
  • β†’Branching strategy keeps new test development isolated.
  • β†’Pull requests enforce peer review of automation changes.
  • β†’Tags mark stable, release-ready suite versions.
πŸ”„
Interview Prep⭐ Interview Focus#23

End-to-End Framework Execution Flow

The complete sequence from feature file creation to report generation.

Understanding the complete execution lifecycle is essential for explaining your framework confidently in interviews. Every BDD automation run follows this deterministic sequence, with each component playing a precisely defined role.

Complete Execution Sequence

  • 1. Feature File (.feature) β†’ Gherkin scenarios authored by QA/BA.
  • 2. Runner File β†’ @CucumberOptions configures feature path, glue, tags, plugins.
  • 3. Maven (mvn test) β†’ Triggers test execution lifecycle.
  • 4. Cucumber Engine β†’ Reads feature files, matches steps to step definitions.
  • 5. Hooks @Before β†’ BaseTest.setup() launches browser, navigates to URL.
  • 6. Step Definition β†’ Executes Java code, calls Page Object methods.
  • 7. Page Object Model β†’ Interacts with web elements using Selenium.
  • 8. Assertions β†’ TestNG/JUnit asserts validate expected outcomes.
  • 9. Hooks @After β†’ Screenshots captured on failure, browser closed.
  • 10. Reports β†’ Extent/Allure HTML dashboards generated in target/.
  • 11. Jenkins β†’ Publishes results, archives artifacts, sends notifications.
🎯
Interview Prep⭐ Interview Focus#24

Most Asked Interview Questions

10 most commonly asked BDD framework questions with strong, structured answers.

These are the questions you will face in every QA/SDET interview. Study these with the framework context in mind β€” always anchor your answers to real project experience.

Top 10 BDD Interview Questions

  • 1. Explain your automation framework architecture. β†’ Describe BDD + POM + Hooks + Utilities flow.
  • 2. Why do you use Page Object Model? β†’ Separation of locators from test logic; single place to maintain UI changes.
  • 3. What is the difference between a Feature File and Step Definition? β†’ Feature = English scenario; Step Definition = Java implementation.
  • 4. Explain Hooks in Cucumber. β†’ @Before/@After for browser lifecycle, screenshot capture, test setup.
  • 5. What does the Runner file do? β†’ Wires feature path + glue path + tags + plugins for test execution.
  • 6. How do you handle synchronization in your framework? β†’ Explicit Wait via WebDriverWait; never Thread.sleep().
  • 7. How do you capture screenshots on failure? β†’ @After hook + TakesScreenshot.getScreenshotAs() + scenario.attach().
  • 8. How do you handle parallel execution? β†’ ThreadLocal driver + @DataProvider(parallel=true) + testng.xml thread-count.
  • 9. How does your framework integrate with Jenkins? β†’ Jenkinsfile + mvn test command + JUnit XML report publishing.
  • 10. How do you manage test data? β†’ Scenario Outline for inline data; Apache POI ExcelUtility for large datasets.
πŸ†
Interview Prep#25

Advantages of BDD Framework

Why BDD is the preferred choice for enterprise QA automation projects.

BDD frameworks deliver compounding advantages across the entire software delivery team β€” from business clarity at the requirement stage to rapid defect discovery in production pipelines.

Key Core Points

  • βœ“Business Readability β€” Non-technical stakeholders can read and validate test scenarios directly.
  • βœ“Living Documentation β€” Feature files are always current specification documents.
  • βœ“Collaborative Ownership β€” QA, Dev, and BA jointly own test scenarios.
  • βœ“Reusable Step Library β€” Common steps (login, navigation) are written once and reused across all features.
  • βœ“Scalable Architecture β€” New features add feature files and step definitions without restructuring.
  • βœ“Faster Debugging β€” Clear step-by-step failure logs pinpoint failures instantly.
  • βœ“Rich Reporting β€” Extent/Allure dashboards communicate results to all stakeholders.
  • βœ“CI/CD Ready β€” Maven + Jenkins execute the full suite on every code push.
  • βœ“Data-Driven Support β€” Scenario Outline + Excel integration enables parameterized testing.
  • βœ“Parallel Execution β€” Reduces regression suite runtime significantly.
πŸ—£οΈ
Interview Prep⭐ Interview Focus#26

How to Explain Your Framework in Interviews

The optimal sequence to explain your BDD framework that creates a strong impression.

Most candidates describe individual tools in isolation β€” Selenium, Cucumber, Maven β€” without demonstrating how they connect. The strongest interview answers explain the architectural flow: how each component depends on the others to deliver reliable, scalable automation.

Recommended Framework Explanation Sequence

  • 1. Framework Type β†’ "We use a BDD framework with Selenium, Cucumber, Java, and Maven."
  • 2. Architecture Overview β†’ "The framework follows POM design β€” locators are separated from test logic."
  • 3. Project Structure β†’ "Feature files in resources/, step definitions and page classes in java/."
  • 4. Execution Entry Point β†’ "TestRunner class uses @CucumberOptions to define feature paths, glue, and tags."
  • 5. Lifecycle Management β†’ "Hooks handle browser initialization in @Before and screenshot capture in @After."
  • 6. Page Object Model β†’ "Every page has a dedicated class with @FindBy elements and interaction methods."
  • 7. Utilities β†’ "ExcelUtility reads test data, WaitUtility handles synchronization, Log4j handles logging."
  • 8. Reporting β†’ "Extent Report generates an HTML dashboard with screenshots embedded on failures."
  • 9. CI/CD β†’ "Jenkinsfile triggers the suite on every Git push, publishes JUnit XML and Allure reports."
  • 10. Parallel Execution β†’ "ThreadLocal driver + DataProvider(parallel=true) runs 4 scenarios simultaneously."
πŸ—„οΈ
Interview Prep⭐ Interview Focus#27

Q27: Dynamic Database Verification & Rollbacks

How to perform database assertions in Cucumber step definitions and execute clean transaction rollbacks.

Verification of database state is a critical step in end-to-end BDD tests (e.g. validating that a signup scenario actually created a row with correct values). In Cucumber frameworks, database assertions are handled in step definitions using JDBC utility classes, while cleanup is managed via @After hooks to avoid polluting shared databases.

DatabaseStepVerification.java
Java
// DbUtility.java β€” Direct JDBC helper
public class DbUtility {
    private static Connection conn;

    public static void establishConnection() throws SQLException {
        String dbUrl = ConfigReader.get("db.url");
        String user = ConfigReader.get("db.username");
        String password = ConfigReader.get("db.password");
        conn = DriverManager.getConnection(dbUrl, user, password);
    }

    public static ResultSet executeQuery(String query) throws SQLException {
        Statement stmt = conn.createStatement();
        return stmt.executeQuery(query);
    }

    public static void closeConnection() throws SQLException {
        if (conn != null && !conn.isClosed()) {
            conn.close();
        }
    }
}

// Step Definition assertion
@Then("the user record should exist in the database with status {string}")
public void verifyUserInDatabase(String expectedStatus) throws Exception {
    String query = "SELECT status FROM users WHERE email = '" + pm.environment.get("tempEmail") + "'";
    DbUtility.establishConnection();
    ResultSet rs = DbUtility.executeQuery(query);
    
    Assert.assertTrue(rs.next(), "User record not found in database.");
    String actualStatus = rs.getString("status");
    Assert.assertEquals(actualStatus, expectedStatus, "Database status mismatch.");
    DbUtility.closeConnection();
}

Core Framework Benefits

  • β†’Ensures end-to-end data integrity.
  • β†’Direct DB assertions are highly robust and prevent false positives.
  • β†’Executing cleanup in @After hooks guarantees dynamic cleanups even on test failures.
πŸ’‰
Interview Prep⭐ Interview Focus#28

Q28: Constructor Dependency Injection (PicoContainer)

Sharing state between separate Step Definition classes cleanly without static variables.

Using static variables to share state between Cucumber step definitions leads to thread safety issues, especially during parallel execution. Constructor Dependency Injection via PicoContainer is the standard BDD solution β€” it automatically initializes and injects a shared container context object into steps.

ConstructorDependencyInjection.java
Java
<!-- Add dependency to pom.xml -->
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-picocontainer</artifactId>
  <version>7.15.0</version>
  <scope>test</scope>
</dependency>

---

// 1. Create a Shared Context Class
public class TestContext {
    public WebDriver driver;
    public Map<String, Object> scenarioData = new HashMap<>();
}

// 2. Inject into Step Definition A
public class LoginSteps {
    private final TestContext context;

    public LoginSteps(TestContext context) {
        this.context = context;
    }

    @Given("the user is logged in")
    public void userLoggedIn() {
        context.scenarioData.put("userId", "12345");
    }
}

// 3. Inject into Step Definition B (Shares the same context instance!)
public class OrderSteps {
    private final TestContext context;

    public OrderSteps(TestContext context) {
        this.context = context;
    }

    @Then("the order should be placed for the logged-in user")
    public void verifyOrder() {
        String userId = (String) context.scenarioData.get("userId");
        System.out.println("Placing order for user: " + userId);
    }
}

Core Framework Benefits

  • β†’Complete thread isolation for parallel execution.
  • β†’Eliminates fragile and dirty static states.
  • β†’Encourages clean, modular step definitions across multiple classes.
πŸƒ
Interview Prep⭐ Interview Focus#29

Q29: Dynamic Dry Run Configuration

Using dryRun to validate Step Definition bindings without launching expensive browser sessions.

Dry run validation is an optimization strategy in Cucumber. Setting dryRun = true in @CucumberOptions scans all feature files and matches them against existing step definitions, reporting any undefined steps immediately without launching browsers or executing the actual test logic.

DryRunSetup.java
Java
// TestRunner.java
@CucumberOptions(
    features = "src/test/resources/features",
    glue = {"stepdefinitions", "hooks"},
    dryRun = true,  // <-- Set to true for validation
    monochrome = true,
    plugin = {"pretty"}
)
public class DryRunner extends AbstractTestNGCucumberTests {}

// Dynamic run from Maven console
mvn test -Dcucumber.plugin="pretty" -Dcucumber.features="src/test/resources" -Dcucumber.execution.dry-run=true

Core Framework Benefits

  • β†’Saves massive pipeline build time on syntax errors.
  • β†’Identifies missing step implementations instantly before server spin-ups.
  • β†’Highly recommended as a pre-commit or pre-merge gate.
πŸͺŸ
Interview Prep⭐ Interview Focus#30

Q30: Multi-Window & iframe Context Switching

Managing complex multi-window, frame, and shadow DOM context transitions in steps.

Modern web applications frequently use iframes (e.g. Stripe checkout forms) or open secondary tabs (e.g. OAuth logins). Step definitions must transition the Selenium driver focus cleanly using window handles or frame switches, wrapping the transitions in explicit waits to prevent flakiness.

ContextSwitches.java
Java
// Switching to an iframe step
@When("the user fills payment details inside the secure frame")
public void fillDetailsInFrame() {
    WebDriver driver = BaseTest.getDriver();
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    
    // 1. Wait for frame and switch
    wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("stripe-frame")));
    
    // 2. Interact with element inside frame
    driver.findElement(By.id("card-number")).sendKeys("4242 4242 4242");
    
    // 3. Switch back to default content
    driver.switchTo().defaultContent();
}

// Switching to a newly opened tab
@Then("the terms page should open in a new window tab")
public void switchToTab() {
    WebDriver driver = BaseTest.getDriver();
    String parentWindow = driver.getWindowHandle();
    
    // Wait until there are exactly 2 windows open
    new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(d -> d.getWindowHandles().size() == 2);
        
    for (String windowHandle : driver.getWindowHandles()) {
        if (!windowHandle.equals(parentWindow)) {
            driver.switchTo().window(windowHandle);
            break;
        }
    }
    Assert.assertTrue(driver.getCurrentUrl().contains("/terms-of-service"));
    driver.close(); // Close tab
    driver.switchTo().window(parentWindow); // Switch back
}

Core Framework Benefits

  • β†’Prevents NoSuchFrameException timing issues.
  • β†’Ensures precise handling of OAuth and Stripe payment gates.
  • β†’Explicitly closes secondary tabs to prevent memory leakage.
🏷️
Interview Prep⭐ Interview Focus#31

Q31: Complex Cucumber Tag Expressions

Executing targeted tests using boolean AND, OR, and NOT tag combinations.

Cucumber supports tag filters to organize test runs dynamically. In modern Cucumber versions, tag filters use standard boolean expressions (and, or, not) to construct complex filter rules, allowing teams to execute highly targeted test suites (e.g., executing smoke tests that do not require mobile browsers).

TagFilter.feature
Gherkin
# Example of tagged scenarios
@smoke @regression
Scenario: Verify smoke login
  Given user is on login page

@regression @slow @database
Scenario: Verify database sync
  Given user triggers bulk sync

---

# Execute in TestRunner.java:
tags = "@regression and not @slow"  # Run regression, skip slow

# Execute from Maven CLI:
mvn test -Dcucumber.filter.tags="@smoke or (@regression and not @database)"

Core Framework Benefits

  • β†’Highly flexible test suite organization.
  • β†’Exclude heavy database or slow tests dynamically in fast-feedback PR runs.
  • β†’Allows simple syntax compared to old Cucumber tilde symbol syntax.
πŸ“Š
Interview Prep⭐ Interview Focus#32

Q32: Scenario Outline vs. Step Data Tables

Deciding between scenario iteration with Examples vs. passing structural tables into steps.

Scenario Outlines are used when the ENTIRE test flow must be executed repeatedly for different rows of data (e.g. testing login with 3 different credentials). Data Tables are used when a single step requires a complex grid of data (e.g. submitting a form with 10 fields) in a single scenario run.

DataStructures.feature
Gherkin
# Scenario Outline: Runs 3 separate times (3 browser setups/teardowns)
Scenario Outline: Login with multi-roles
  When user logs in as "<role>"
  Then dashboard should show "<access>"
  Examples:
    | role   | access   |
    | admin  | Full     |
    | member | ReadOnly |

---

# Step Data Table: Runs ONCE (passes grid of data to one step)
Scenario: Create user with profile data
  When the user submits the profile registration form:
    | Field      | Value            |
    | FirstName  | Alex             |
    | LastName   | SDET             |
    | Department | Quality Assurance|

Core Framework Benefits

  • β†’Scenario Outline tests boundaries cleanly across separate runs.
  • β†’Data Tables collapse boilerplate UI step repetitions into single interactions.
  • β†’Data Tables are parsed cleanly using Cucumber Maps: List<Map<String, String>>.
πŸ”Œ
Interview Prep⭐ Interview Focus#33

Q33: Hybrid End-to-End API + UI Testing

Combining Rest-Assured API calls and Selenium UI checks in a single scenario.

Running full UI tests for setup steps (like creating a user, verifying emails, setting up products) is slow and flaky. A hybrid framework uses REST-Assured API calls in @Before hooks or step definitions to instantaneously create the test pre-conditions, then uses Selenium UI to verify only the target user interaction.

HybridTesting.java
Java
// Step definition executing Rest-Assured API setup
@Given("a product exists in the system with name {string}")
public void apiProductSetup(String productName) {
    // 1. Send fast backend API request to create the product
    Response response = RestAssured.given()
        .header("Content-Type", "application/json")
        .body("{\"name\":\"" + productName + "\",\"price\":99.99}")
        .post("https://api.example.com/products");
        
    Assert.assertEquals(response.getStatusCode(), 201);
    String productId = response.jsonPath().getString("id");
    pm.environment.set("tempProductId", productId); // Save ID for UI use
}

@When("the user searches for the product on the shop dashboard")
public void uiProductSearch() {
    // 2. Open browser and search via UI
    BaseTest.getDriver().get("https://shop.example.com");
    shopPage.searchFor(pm.environment.get("tempProductId"));
}

Core Framework Benefits

  • β†’Saves over 80% of test setup runtime.
  • β†’Reduces flakiness by bypassing non-target page navigations.
  • β†’Simulates realistic multi-layer integrations in a single BDD run.
πŸ•΅οΈ
Interview Prep⭐ Interview Focus#34

Q34: Debugging Headless CI/CD Failures

Resolving timing and resolution mismatches that occur only inside headless pipeline runs.

A classic SDET pain point is a BDD test that passes locally but fails in Jenkins. This is usually caused by: 1) Timing differences (pipelines are slower, requiring larger explicit waits), 2) Screen resolution differences (headless defaults to a small screen, hiding elements), or 3) Dynamic content loads. Debugging requires local headless simulation, window-maximization enforcement, and screenshot evaluations.

HeadlessChromeSetup.java
Java
// Enforcing resolutions inside BaseTest.java for Headless Chrome
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");

// Crucial: Headless browsers default to tiny sizes! Explicitly set resolution:
options.addArguments("--window-size=1920,1080");

WebDriver driver = new ChromeDriver(options);
// Double-enforce size
driver.manage().window().setSize(new Dimension(1920, 1080));

Core Framework Benefits

  • β†’Eliminates mysterious ElementClickInterceptedException failures.
  • β†’Guarantees layout uniformity across pipeline containers.
  • β†’Matches visual dimensions between developers and Jenkins.
🎨
Interview Prep⭐ Interview Focus#35

Q35: Monochrome & Strict Parameters

Configuring console output styling and step failure behaviors.

Monochrome and Strict are core configuration switches inside @CucumberOptions. monochrome = true strips out colored ANSI character codes from console logs, producing clean, plain-text logs suitable for Jenkins build histories. strict = true forces the test run to fail if any undefined or pending step is encountered.

MonochromeRunner.java
Java
// TestRunner.java Options
@CucumberOptions(
    features = "src/test/resources/features",
    glue = {"stepdefinitions"},
    monochrome = true, // Strips ANSI codes, clean plain text logs
    plugin = {
        "pretty", 
        "html:target/report.html"
    }
)
public class MonochromeRunner extends AbstractTestNGCucumberTests {}

Core Framework Benefits

  • β†’Prevents corrupted ANSI logs in CI build dashboards.
  • β†’Guarantees fail-fast pipeline executions on undefined step definitions.
  • β†’Simplifies console log search indexing.
βš™οΈ
Interview Prep⭐ Interview Focus#36

Q36: Maven Dynamic Environment Routing

Routing environment configurations dynamically from command-line overrides.

To prevent environment settings from being hardcoded inside the repository, modern frameworks read properties using Maven system variables. The CI/CD system passes the target browser and environment dynamically (e.g. mvn test -Denv=staging), and ConfigReader.java resolves them at runtime.

ConfigReader.java
Java
// ConfigReader.java - Resolving dynamic command-line parameters
public class ConfigReader {
    private static Properties properties;

    static {
        try {
            // 1. Get environment key from Maven CLI -Denv=... (default to 'qa')
            String env = System.getProperty("env");
            if (env == null) env = "qa";
            
            String configPath = "src/test/resources/config/" + env + "-config.properties";
            FileInputStream fis = new FileInputStream(configPath);
            properties = new Properties();
            properties.load(fis);
        } catch (IOException e) {
            throw new RuntimeException("Failed to load env configurations.", e);
        }
    }

    public static String get(String key) {
        // Allow command line property overrides over file property overrides
        String systemProp = System.getProperty(key);
        if (systemProp != null) return systemProp;
        return properties.getProperty(key);
    }
}

Core Framework Benefits

  • β†’Zero environment credentials stored in static files.
  • β†’Seamless switches between Dev, Staging, and Production zones.
  • β†’Allows developers to run local environments with ease.
⚠️
Interview Prep⭐ Interview Focus#37

Q37: Duplicate Step Definition Binding Error

Resolving duplicate step definitions and step matching conflicts.

A DuplicateStepDefinitionException is thrown by the Cucumber engine when a Gherkin feature step matches two or more step definition expressions in the codebase. Resolving this requires refining the regular expressions or step text to make them globally unique.

StepBindingResolution.java
Java
// ❌ Conflict: Both regexes match "Given the user clicks on login"
@Given("^the user clicks on (.*)$")
public void clickAny(String element) {}

@Given("^the user clicks on login$")
public void clickLogin() {}

// βœ… Resolution: Refine regex bounds or use exact Cucumber Expressions
@Given("the user clicks on {string}") // Matches specific quoted text only
public void clickSpecific(String element) {}

@Given("the user clicks on the login button") // Strict string match
public void clickLoginStrict() {}

Core Framework Benefits

  • β†’Clean step resolution patterns.
  • β†’Standardizes dynamic parameters.
  • β†’Ensures clarity for BAs authoring feature files.
🎫
Interview Prep⭐ Interview Focus#38

Q38: Dynamic Jira Test Integration (Xray)

Pushing Cucumber execution results dynamically to Jira tickets inside CI/CD.

In enterprise QA environments, test execution results must be logged in test management tools like Xray. BDD maps scenario tags containing JIRA IDs directly to test issues in Jira, and Jenkins triggers a post-execution script that pushes the generated cucumber.json report to Xray REST APIs.

JenkinsfilePostActions.groovy
Groovy / Jenkinsfile
# Feature file tagged with Jira Test ID
@Jira-TEST-4561 @regression
Scenario: Verify checkout payment flow
  Given user has items in cart
  When user completes payment

---

# Groovy Jenkinsfile post-actions pushing report to Xray API
post {
    always {
        // Push the JSON report using cURL and Xray authentication
        sh """
            curl -H "Content-Type: multipart/form-data" \
                 -u admin:adminPassword \
                 -F "file=@target/cucumber-reports/report.json" \
                 https://jira.company.com/rest/raven/2.0/import/execution/cucumber
        """
    }
}

Core Framework Benefits

  • β†’Real-time Jira test metrics dashboards.
  • β†’Eliminates manual logging tasks for QAs.
  • β†’100% trace-link mapping between requirements and executions.
πŸ—£
Interview Prep⭐ Interview Focus#39

Q39: Cucumber Expressions vs. RegEx

Comparing standard parameter bindings against complex regex matches.

Cucumber Expressions are the modern standard for writing step bindings. They replace hard-to-read regular expressions with clear parameter types like {string}, {int}, and {float} β€” reducing binding errors and making steps self-documenting.

CucumberExpressions.java
Java
// ❌ Old Regex binding - complex, prone to grouping mistakes
@Given("^the user has (\\d+) items in their (cart|wishlist)$")
public void oldRegexStep(int itemCount, String listType) {}

// βœ… Modern Cucumber Expression - clean, readable, typesafe
@Given("the user has {int} items in their {string}")
public void modernExpressionStep(int itemCount, String listType) {}

Core Framework Benefits

  • β†’Typesafe parameter resolution automatically executed.
  • β†’Massively improves step readability for developers.
  • β†’Simpler syntax lowers onboarding time.
πŸš€
Interview Prep⭐ Interview Focus#40

Q40: Pipeline Branch-Level dynamic tags

Routing test execution tags dynamically based on active git branches.

To keep developer pipelines fast, you should run different sets of tests based on the Git branch. For example, feature branches should run only lightweight @smoke tests, while the main branch integration builds run the full @regression suite. This is configured dynamically in the Jenkinsfile.

DynamicTagRouting.groovy
Groovy / Jenkinsfile
// Dynamic tag routing inside Jenkinsfile pipeline
stage('Execute BDD Tests') {
    steps {
        script {
            // Determine tag based on git branch name
            String testTag = "@smoke"
            if (env.BRANCH_NAME == 'main') {
                testTag = "@regression"
            }
            
            // Execute Maven with dynamic tag routing
            sh "mvn test -Dcucumber.filter.tags='${testTag}' -Dthreads=4"
        }
    }
}

Core Framework Benefits

  • β†’Spreads feedback cycles logically.
  • β†’Protects integration branches with absolute regressions.
  • β†’Minimizes overall computing cost.

Done practicing?

Return to the dashboard to monitor your overall progress across all interview prep tracks.

🏠 Back to Home Dashboard