Setting up Cucumber requires three Maven dependencies, a specific project structure, and a runner class. Let us do it step by step.
<dependencies>
<!-- Cucumber Core -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
<!-- Cucumber + TestNG integration -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
<!-- Selenium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.18.1</version>
</dependency>
<!-- TestNG -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>Keep cucumber-java and cucumber-testng versions the same. Mismatched versions cause cryptic ClassNotFoundException errors. If you use 7.15.0 for cucumber-java, use 7.15.0 for cucumber-testng too.
my-cucumber-project/
├── pom.xml
├── src/
│ └── test/
│ ├── java/
│ │ └── com/autopractice/
│ │ ├── runner/
│ │ │ └── TestRunner.java ← Entry point
│ │ ├── stepdefinitions/
│ │ │ ├── LoginSteps.java ← Step definitions
│ │ │ ├── DashboardSteps.java
│ │ │ └── ShoppingSteps.java
│ │ ├── hooks/
│ │ │ └── Hooks.java ← Browser setup/teardown
│ │ └── pages/
│ │ ├── LoginPage.java ← Page Objects
│ │ └── DashboardPage.java
│ └── resources/
│ └── features/ ← Feature files
│ ├── banking/
│ │ ├── login.feature
│ │ └── dashboard.feature
│ └── shopping/
│ ├── search.feature
│ └── cart.feature
└── target/cucumber-reports/ ← Generated reportsNotice: feature files go in src/test/resources/features. Step definitions go in src/test/java. This separation is intentional — feature files are readable by everyone, Java code is for the automation team.
The runner class tells Cucumber where to find feature files and step definitions. It extends AbstractTestNGCucumberTests and uses @CucumberOptions for configuration.
package com.autopractice.runner;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;
@CucumberOptions(
features = "src/test/resources/features",
glue = {"com.autopractice.stepdefinitions",
"com.autopractice.hooks"},
plugin = {
"pretty",
"html:target/cucumber-reports/report.html",
"json:target/cucumber-reports/report.json"
},
monochrome = true
)
public class TestRunner extends AbstractTestNGCucumberTests {
@Override
@DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}| Option | What It Does | Example |
|---|---|---|
| features | Path to feature files | "src/test/resources/features" |
| glue | Packages with step definitions and hooks | {"com.autopractice.stepdefinitions"} |
| plugin | Report format and output path | {"html:target/report.html"} |
| tags | Filter scenarios by tags | "@smoke and not @wip" |
| monochrome | Clean console output (no special chars) | true |
| dryRun | Check step mappings without running tests | true |
Use dryRun = true when writing new feature files. Cucumber will scan your steps and tell you which ones are missing definitions — without launching a browser. Set it back to false when you are ready to run actual tests.
Q: How do you set up Cucumber in a Maven project?
A: Three dependencies in pom.xml: cucumber-java, cucumber-testng, and selenium-java. Feature files go in src/test/resources/features. Step definitions go in src/test/java. The runner class extends AbstractTestNGCucumberTests with @CucumberOptions that specifies the features path, glue package, report plugins, and tags. Run with mvn test or right-click the runner in IntelliJ.
Key Point: Add cucumber-java + cucumber-testng to Maven. Feature files in resources/features. Runner class with @CucumberOptions.