Back to Courses
SELENIUM TESTER? ADD BDD TO YOUR SKILL SET

BDD with Cucumber & Java

A hands-on course covering Gherkin, Feature Files, Step Definitions, Hooks, Data-Driven Testing, PicoContainer Dependency Injection, Page Object Model, ExtentReports, and a complete BDD automation framework.

15+
Days of Training
13
Modules
60+
Topics Covered
Live
Framework

 Who Is This Course For?

This course is for Selenium with Java engineers who want to implement BDD in their automation framework. You will build a complete BDD framework using Cucumber, JUnit, PicoContainer Dependency Injection, Page Object Model, and ExtentReports — the way real Agile teams actually work.

Cucumber + JUnit Gherkin & Feature Files PicoContainer DI Page Object Model ExtentReports Complete BDD Framework

🚀 Course Progression

Each module builds toward a fully integrated BDD automation framework.

1BDD Concepts
2Gherkin & Cucumber
3Selenium + DI
4Full Framework
🏆BDD Ready!
MODULE 01  Introduction to BDD & Gherkin
Why this matters: BDD is asked about in almost every Agile QA interview. Understanding why it exists — not just how to use it — lets you answer "why BDD?" with real confidence and real examples.
BDD & Agile Collaboration
  • What BDD (Behavior Driven Development) is — a process where Customer, BA, Dev, and QA collaborate using a shared language
  • Three phases of BDD: Discovery (requirement discussion), Formulation (documentation), Automation (software/test implementation)
  • The core problem BDD solves — "secure" means authentication to a dev, "sign-in" to QA, "access control" to a customer
Gherkin Language
  • Given — precondition; When — action performed; Then — expected outcome
  • And keyword — chaining multiple Given / When / Then steps
  • Gherkin is framework-agnostic — same syntax works in Cucumber (Java), Behave (Python), SpecFlow (.NET)
  • Writing a complete Login scenario using Given / When / Then / And
MODULE 02  Project Setup & Maven Configuration
Why this matters: Getting the project structure and dependencies right from the start saves hours of debugging later. Understanding each dependency's purpose makes you self-sufficient when setting up a BDD project from scratch.
IDE & Plugin Setup
  • Eclipse Maven project creation — src/test/java for code, src/test/resources for .feature files
  • Installing Cucumber Eclipse Plugin from Eclipse Marketplace — enables syntax highlighting for .feature files
  • Natural plugin (optional) — Gherkin auto-completion while editing feature files
Maven Dependencies
  • cucumber-java — write step definitions in Java using @Given, @When, @Then
  • cucumber-junit — JUnit-based test runner; @RunWith(Cucumber.class)
  • selenium-java — WebDriver API for browser automation
  • webdrivermanager — auto-manages browser driver binaries; no manual path setup
  • cucumber-picocontainer — enables constructor-based Dependency Injection across step classes
  • extentreports — generates rich HTML reports with charts and screenshots
MODULE 03  Feature Files & Gherkin Syntax
Why this matters: The feature file is the heart of BDD — it's what your whole team reads. Writing clean, well-structured feature files is the first skill anyone assessing your BDD knowledge will look at.
Feature File Structure
  • File extension: .feature — create under src/test/resources/features
  • Feature keyword + description — explains what this file covers
  • Comments using # — different from Java's //
  • Scenario keyword — one test case; name it clearly and uniquely
  • Duplicate scenario names are allowed in feature files; duplicate step definition annotations are not
Background
  • Background — a set of steps that run before every scenario in the same .feature file
  • Limitation: Background only supports setup (before), not teardown (after); scoped to one file only
  • Background with Scenario Outline — runs once per iteration, not once total
  • Background vs Hooks: Background is visible in the file; Hooks run silently in the background
MODULE 04  Step Definitions & Cucumber Expressions
Why this matters: Step definitions are where Gherkin meets Java. Getting the matching rules right — and knowing how to pass data between the feature file and Java — is essential for building any real BDD framework.
Step Definitions
  • Annotations @Given, @When, @Then — the text must exactly match the Gherkin sentence (case-sensitive, space-sensitive)
  • Unique annotation rule — two methods with the same text throw AmbiguousStepDefinitionsException
  • Step definitions are package-scoped, not class-scoped — glue searches all classes in the package
  • snippets = SnippetType.CAMELCASE — generates camelCase Java stubs matching Gherkin steps
Cucumber Expressions & Parameter Types
  • Modern Cucumber Expressions: {string}, {int}, {float}, {double}, {word}, {long}
  • Anonymous parameter {} — accepts any value when the data type is not known in advance
  • Legacy Regular Expressions — ^ (beginning), $ (end), capture groups (.*) for dynamic values
  • Passing runtime values (username, password) from the feature file step to Java method arguments
MODULE 05  Test Runner & CucumberOptions
Why this matters: The test runner is the control panel for your entire BDD suite. Knowing every option — especially dryRun, plugins, and tags — gives you precise control over what runs, when, and in what format.
Test Runner Setup
  • @RunWith(Cucumber.class) — tells JUnit to use Cucumber as the test executor
  • @CucumberOptions(features = "src/test/resources/features") — path to feature files
  • glue = "stepdefinitions" — package where step definitions and hooks are located
CucumberOptions Attributes
  • dryRun = true — validates every step has a matching method without executing anything
  • plugin = {"pretty"} — formatted Gherkin output in the console
  • plugin = {"html:target/report.html"} — built-in HTML report
  • plugin = {"json:target/report.json"} — JSON output for third-party reporting tools
  • tags — run only scenarios matching a tag expression
  • snippets = SnippetType.CAMELCASE — camelCase method stub generation on undefined steps
MODULE 06  Tags & Execution Control
Why this matters: In large projects with hundreds of scenarios, running everything every time is not practical. Tags let you run only smoke tests before a release, or only regression tests overnight — a skill every senior QA uses daily.
Tags
  • Adding tags to a Scenario: @smoke, @regression, @sanity, @wip
  • Adding a tag to a Feature — all scenarios inside inherit that tag automatically
  • Multiple tags on one scenario: @smoke @regression — both apply independently
Tag Logical Operators
  • @smoke or @regression — run scenarios that have either tag (OR)
  • @smoke and @regression — run only scenarios that have both tags (AND)
  • not @smoke — exclude all @smoke scenarios from this run
  • Combining operators: (@smoke or @regression) and not @wip
MODULE 07  Data-Driven Testing — Scenario Outline & DataTable
Why this matters: Almost every real test needs to run with multiple sets of data. Knowing both approaches — and when to use each — is one of the most common BDD interview questions and one of the most practical daily skills.
Scenario Outline + Examples
  • Scenario Outline — repeat the entire scenario for every row in the Examples table
  • Examples table — pipe-delimited (|); first row is the header used as placeholders
  • Placeholder syntax in steps: <username>, <password> — replaced at runtime with each row's values
  • Use when: all steps in the scenario must run again for each dataset
DataTable
  • DataTable — pass multiple values to a single step, not the whole scenario
  • Use when: only one step needs multiple inputs (e.g. entering a list of credentials)
  • dataTable.asList() — flat List<String> of all values
  • dataTable.asLists()List<List<String>> — rows and columns
  • dataTable.asMaps()List<Map<String, String>> — header row becomes the key
  • Key interview question: Scenario Outline vs DataTable — what is the difference and when do you use each?
MODULE 08  Hooks & Test Lifecycle
Why this matters: Hooks are how professional frameworks handle setup and teardown without repeating code in every test. They're also where browser launch, report creation, and screenshot capture happen — all automatically.
Hook Annotations
  • @Before — runs before every scenario; equivalent to @BeforeMethod in TestNG
  • @After — runs after every scenario; receives optional Scenario object
  • @BeforeAll — runs once before the entire suite; method must be static
  • @AfterAll — runs once after the entire suite; method must be static
  • @BeforeStep / @AfterStep — runs before/after each individual step
Controlling Hook Behaviour
  • order attribute — multiple hooks run in descending order (higher number runs first)
  • Conditional hooks: @Before("@smoke") — runs only for scenarios tagged @smoke
  • Hooks run silently — not shown in built-in reports unless you add explicit log statements
  • Hook class name is irrelevant — only the annotation matters; glue picks them up automatically
  • scenario.isFailed() in @After — check if the scenario failed, then take a screenshot
MODULE 09  Selenium WebDriver Integration
Why this matters: Integrating Selenium into a BDD framework has specific rules that trip up most beginners — you cannot just copy your Selenium setup from a regular project. Getting it right here makes the rest of the framework solid.
Topics Covered
  • Adding selenium-java and webdrivermanager dependencies to pom.xml
  • Initializing WebDriver in @Before: WebDriverManager.chromedriver().setup(); driver = new ChromeDriver();
  • Opening the application URL: driver.get("https://...")
  • Closing the browser: driver.quit() in @After
  • Static WebDriver approach — simple, works for single-thread runs; does not support parallel execution
  • Why Cucumber forbids extends between a hooks class and step definition class — leads to Dependency Injection
MODULE 10  Dependency Injection with PicoContainer
Why this matters: This is the most asked-about architectural topic in BDD interviews. Understanding why PicoContainer is needed — and how constructor injection works — proves you understand professional framework design, not just scripting.
Why Dependency Injection
  • Problem: multiple step definition classes all need the same WebDriver, but Cucumber forbids extends
  • DI concept: instead of each class creating its own object, one object is created and injected into all classes that need it
  • Analogy — same as TestNG injecting ITestResult into @AfterMethod automatically
PicoContainer Implementation
  • Add cucumber-picocontainer to pom.xml
  • Create BaseDriver shared class — contains public WebDriver driver (and later ExtentTest test)
  • Constructor injection in every class: public LoginSteps(BaseDriver baseDriver) { this.baseDriver = baseDriver; }
  • PicoContainer automatically creates one BaseDriver instance per scenario and injects it everywhere
  • Access WebDriver everywhere via baseDriver.driver — no static fields needed
  • Same pattern applies to Hooks, step definition classes, page classes — all get the same instance
MODULE 11  Page Object Model in BDD Framework
Why this matters: POM keeps your framework maintainable as the application grows. Combining POM with the BDD structure requires careful design — and explaining that design clearly is what separates experienced BDD developers from beginners.
Topics Covered
  • Creating a pages package — one class per application page (e.g. LoginPage, HomePage)
  • @FindBy annotations for element declaration; PageFactory.initElements(driver, this) for initialization
  • Page action methods: enterUsername(String user), enterPassword(String pass), clickLoginButton()
  • Accessing page objects from step definitions: new LoginPage(baseDriver.driver)
  • Storing commonly used page objects in BaseDriver for universal access
  • Framework folder structure — features/, stepdefinitions/, pages/, hooks/ — organised by module
MODULE 12  ExtentReports Integration
Why this matters: The built-in Cucumber report shows you what ran, but not what happened. ExtentReports shows each step, its result, and attached screenshots — the kind of evidence managers and clients actually want to see.
Setup & Configuration
  • Add extentreports Maven dependency
  • ExtentSparkReporter sparkReporter = new ExtentSparkReporter("target/extent-report.html")
  • ExtentReports reports = new ExtentReports(); reports.attachReporter(sparkReporter);
  • Declare static ExtentReports reports and static ExtentTest test in BaseDriver — accessible everywhere
  • Initialize in @BeforeAll (must be static); flush in @AfterAll: reports.flush()
Logging Test Results
  • Create a test node per scenario: baseDriver.test = reports.createTest(scenario.getName())
  • Log steps: baseDriver.test.info("Navigating to login page")
  • Mark results: test.pass("Login successful") / test.fail("Login failed")
  • Add timestamp to report filename using new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
MODULE 13  Screenshots on Failure & Framework Completion
Why this matters: A framework that silently fails and produces no evidence is useless in a real project. Screenshots on failure — attached to the report automatically — are the professional standard and the final piece of a complete BDD framework.
Screenshot on Failure
  • Check for failure in @After: if (scenario.isFailed()) { ... }
  • Cast WebDriver to TakesScreenshot: ((TakesScreenshot) baseDriver.driver).getScreenshotAs(OutputType.FILE)
  • Save to path using scenario.getName() as filename: target/images/<scenarioName>.png
  • Attach to ExtentReport: baseDriver.test.fail(MediaEntityBuilder.createScreenCaptureFromPath(imgPath).build())
Framework Enhancements & Interview Prep
Timestamp Reports

Append new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) to avoid overwriting previous report files

Jenkins CI/CD

Trigger mvn test from a Jenkins Freestyle job; use HTML Publisher plugin to display ExtentReport inside Jenkins

Selenium Grid

Replace new ChromeDriver() with new RemoteWebDriver(new URL(hubUrl), options) to run on Grid or cloud

Git Integration

Push framework to GitHub; connect Jenkins to the repo for CI-triggered automated test runs on every commit

DI Interview Answer

Explain: "PicoContainer creates one BaseDriver instance and injects it via constructor into every class — no static fields, no inheritance needed"

Background vs Hooks

Background: visible, before only, file-scoped. Hooks: invisible, before+after, suite-wide, supports conditional tags and ordering