JUnit 4 runner that enables executing Cucumber scenarios as JUnit tests, providing integration between Cucumber's behavior-driven development features and JUnit's testing framework
npx @tessl/cli install tessl/maven-io-cucumber--cucumber-junit@7.22.00
# Cucumber JUnit
1
2
Cucumber JUnit is a JUnit 4 runner that enables executing Cucumber scenarios as JUnit tests, providing seamless integration between Cucumber's behavior-driven development (BDD) framework and JUnit's testing infrastructure. It allows developers to execute Cucumber scenarios written in Gherkin as standard JUnit tests, making BDD practices easily accessible within existing JUnit-based testing workflows.
3
4
## Package Information
5
6
- **Package Name**: cucumber-junit
7
- **Package Type**: maven
8
- **Language**: Java
9
- **Installation**: Add to Maven `pom.xml`:
10
```xml
11
<dependency>
12
<groupId>io.cucumber</groupId>
13
<artifactId>cucumber-junit</artifactId>
14
<version>7.22.1</version>
15
<scope>test</scope>
16
</dependency>
17
```
18
19
## Core Imports
20
21
```java
22
import io.cucumber.junit.Cucumber;
23
import io.cucumber.junit.CucumberOptions;
24
import org.junit.runner.RunWith;
25
```
26
27
## Basic Usage
28
29
```java
30
package com.example;
31
32
import io.cucumber.junit.CucumberOptions;
33
import io.cucumber.junit.Cucumber;
34
import org.junit.runner.RunWith;
35
36
@RunWith(Cucumber.class)
37
@CucumberOptions(plugin = "pretty")
38
public class RunCucumberTest {
39
}
40
```
41
42
This creates a JUnit test runner that will execute all Cucumber scenarios in the same package as the runner class. By default, glue code (step definitions and hooks) is also assumed to be in the same package.
43
44
## Architecture
45
46
Cucumber JUnit is built around several key components that integrate Cucumber's BDD framework with JUnit's testing infrastructure:
47
48
- **Cucumber Runner**: The main `Cucumber` class extends JUnit's `ParentRunner` and orchestrates feature execution
49
- **Feature Processing**: Parses Gherkin feature files and creates executable test scenarios using Cucumber Core
50
- **JUnit Integration**: Maps Cucumber scenarios to JUnit test cases with proper descriptions and notifications
51
- **Configuration System**: Layered options parsing from properties files, annotations, environment variables, and system properties
52
- **Plugin System**: Extensible reporting and formatting through Cucumber's plugin architecture
53
- **Parallel Execution**: Thread-safe execution supporting JUnit's `RunnerScheduler` for parallel test execution
54
55
The runner follows JUnit 4's `ParentRunner` pattern, creating child runners for each feature file and mapping scenarios to individual JUnit test cases.
56
57
## Capabilities
58
59
### JUnit Runner
60
61
The main JUnit 4 runner class for executing Cucumber scenarios as JUnit tests.
62
63
```java { .api }
64
@API(status = API.Status.STABLE)
65
public final class Cucumber extends ParentRunner<ParentRunner<?>> {
66
/**
67
* Constructor called by JUnit to create the Cucumber runner.
68
* Parses configuration options, initializes plugins, and creates feature runners.
69
*
70
* @param clazz the test class annotated with @RunWith(Cucumber.class)
71
* @throws InitializationError if feature parsing fails, invalid options are provided,
72
* or the test class contains Cucumber annotations (step definitions/hooks)
73
*/
74
public Cucumber(Class<?> clazz) throws InitializationError;
75
76
/**
77
* Set custom scheduler for parallel execution of feature files.
78
* Enables thread-safe parallel execution across multiple threads.
79
*
80
* @param scheduler the RunnerScheduler implementation to control parallel execution
81
*/
82
public void setScheduler(RunnerScheduler scheduler);
83
}
84
```
85
86
**Usage Example:**
87
```java
88
@RunWith(Cucumber.class)
89
@CucumberOptions(
90
features = "src/test/resources/features",
91
glue = "com.example.steps",
92
tags = "@smoke and not @slow"
93
)
94
public class AcceptanceTest {
95
}
96
```
97
98
### Configuration Options
99
100
Annotation for configuring Cucumber's execution options.
101
102
```java { .api }
103
@API(status = API.Status.STABLE)
104
@Retention(RetentionPolicy.RUNTIME)
105
@Target({ElementType.TYPE})
106
public @interface CucumberOptions {
107
/** Skip glue code execution */
108
boolean dryRun() default false;
109
110
/** Feature file paths */
111
String[] features() default {};
112
113
/** Package paths for step definitions and hooks */
114
String[] glue() default {};
115
116
/** Additional glue packages */
117
String[] extraGlue() default {};
118
119
/** Tag expression for filtering scenarios */
120
String tags() default "";
121
122
/** Register plugins (junit, html, pretty, progress, json, etc.) */
123
String[] plugin() default {};
124
125
/** Publish reports to https://reports.cucumber.io */
126
boolean publish() default false;
127
128
/** Disable colored terminal output */
129
boolean monochrome() default false;
130
131
/** Filter scenarios by name regex */
132
String[] name() default {};
133
134
/** Format of generated snippets */
135
SnippetType snippets() default SnippetType.UNDERSCORE;
136
137
/** Use filename compatible names */
138
boolean useFileNameCompatibleName() default false;
139
140
/** Include steps in notifications */
141
boolean stepNotifications() default false;
142
143
/** Custom ObjectFactory implementation */
144
Class<? extends io.cucumber.core.backend.ObjectFactory> objectFactory() default NoObjectFactory.class;
145
146
/** Custom UuidGenerator implementation */
147
Class<? extends io.cucumber.core.eventbus.UuidGenerator> uuidGenerator() default NoUuidGenerator.class;
148
}
149
```
150
151
**Usage Examples:**
152
153
Basic configuration:
154
```java
155
@CucumberOptions(
156
plugin = "pretty",
157
monochrome = true
158
)
159
```
160
161
Advanced configuration:
162
```java
163
@CucumberOptions(
164
features = {"src/test/resources/features/login", "src/test/resources/features/checkout"},
165
glue = {"com.example.steps", "com.example.hooks"},
166
tags = "@regression and not @slow",
167
plugin = {
168
"pretty",
169
"html:target/cucumber-reports",
170
"json:target/cucumber-reports/Cucumber.json",
171
"junit:target/cucumber-reports/Cucumber.xml"
172
},
173
stepNotifications = true,
174
useFileNameCompatibleName = true
175
)
176
```
177
178
Feature path examples:
179
- `"src/test/resources/features"` - All features in directory
180
- `"classpath:com/example/application"` - All features in package
181
- `"src/test/resources/features/example.feature:42"` - Specific scenario at line 42
182
- `"@target/rerun"` - All scenarios in rerun files
183
184
### Snippet Types
185
186
Enum for configuring the format of generated step definition snippets.
187
188
```java { .api }
189
public enum SnippetType {
190
/** Use underscore style for method names */
191
UNDERSCORE,
192
/** Use camel case style for method names */
193
CAMELCASE
194
}
195
```
196
197
**Usage Example:**
198
```java
199
@CucumberOptions(snippets = SnippetType.CAMELCASE)
200
```
201
202
## Integration Features
203
204
### JUnit Rules Support
205
Cucumber JUnit supports JUnit's `@ClassRule`, `@BeforeClass`, and `@AfterClass` annotations. These execute before and after all scenarios:
206
207
```java
208
@RunWith(Cucumber.class)
209
public class RunCucumberTest {
210
@ClassRule
211
public static TestRule rule = new MyTestRule();
212
213
@BeforeClass
214
public static void setUp() {
215
// Runs before all scenarios
216
}
217
218
@AfterClass
219
public static void tearDown() {
220
// Runs after all scenarios
221
}
222
}
223
```
224
225
**Note:** Using JUnit rules limits portability between runners and may not execute correctly with command line, IntelliJ IDEA, or Cucumber-Eclipse. It's recommended to use Cucumber's `@Before` and `@After` hooks instead.
226
227
### Assume Support
228
Cucumber JUnit supports JUnit's `Assume` functionality for conditional test execution:
229
230
```java
231
import static org.junit.Assume.assumeTrue;
232
233
@Given("^a precondition is met$")
234
public void preconditionCheck() {
235
assumeTrue("Skipping test due to environment", isEnvironmentReady());
236
}
237
```
238
239
Failed assumptions result in test abortion (marked as skipped) rather than failure.
240
241
### Parallel Execution
242
Cucumber JUnit supports parallel execution of feature files across multiple threads. Configure with Maven Surefire plugin:
243
244
```xml
245
<plugin>
246
<artifactId>maven-surefire-plugin</artifactId>
247
<version>3.0.0</version>
248
<configuration>
249
<parallel>both</parallel>
250
<threadCount>4</threadCount>
251
</configuration>
252
</plugin>
253
```
254
255
## Error Handling
256
257
The runner validates configuration and throws `InitializationError` for:
258
- Invalid feature paths
259
- Parsing errors in feature files
260
- Missing or invalid glue packages
261
- Plugin configuration issues
262
- Classes with Cucumber annotations (step definitions should be in separate classes)
263
264
Common exceptions during execution:
265
- Step definitions are undefined (generates helpful snippets)
266
- Scenarios are skipped due to failed assumptions
267
- Feature parsing failures due to invalid Gherkin syntax
268
269
### Undefined Step Exception
270
271
Exception thrown when step definitions are missing for scenario steps, providing helpful snippet suggestions.
272
273
```java { .api }
274
/**
275
* Exception thrown when Cucumber encounters undefined steps during execution.
276
* Contains generated code snippets to help implement missing step definitions.
277
*/
278
final class UndefinedStepException extends RuntimeException {
279
/**
280
* Creates exception with snippet suggestions for undefined steps
281
* @param suggestions Collection of step definition suggestions with generated code snippets
282
*/
283
UndefinedStepException(Collection<Suggestion> suggestions);
284
}
285
```
286
287
This exception is thrown automatically by the Cucumber runner when scenarios contain steps that don't have corresponding step definitions. The exception message includes generated code snippets in the configured snippet format (underscore or camelcase).
288
289
## Types
290
291
```java { .api }
292
// JUnit framework types
293
import org.junit.runners.model.InitializationError;
294
import org.junit.runners.model.RunnerScheduler;
295
import org.junit.runner.RunWith;
296
297
// Cucumber JUnit types
298
import io.cucumber.junit.Cucumber;
299
import io.cucumber.junit.CucumberOptions;
300
import io.cucumber.junit.CucumberOptions.SnippetType;
301
302
// Cucumber core types (dependencies)
303
import io.cucumber.core.backend.ObjectFactory;
304
import io.cucumber.core.eventbus.UuidGenerator;
305
import io.cucumber.plugin.event.SnippetsSuggestedEvent.Suggestion;
306
307
// Annotation support
308
import java.lang.annotation.ElementType;
309
import java.lang.annotation.Retention;
310
import java.lang.annotation.RetentionPolicy;
311
import java.lang.annotation.Target;
312
import org.apiguardian.api.API;
313
314
// Java standard library
315
import java.util.Collection;
316
```