0
# Lifecycle Hooks
1
2
Comprehensive hook system for test setup, teardown, and step-level interception across different scopes. Hooks provide precise control over test execution lifecycle with support for conditional execution based on tags and explicit ordering.
3
4
## Capabilities
5
6
### Before Hook
7
8
Execute method before each scenario with optional tag filtering and execution order control.
9
10
```java { .api }
11
/**
12
* Execute method before each scenario
13
* @param value Tag expression for conditional execution (default: "")
14
* @param order Execution order, lower numbers run first (default: 10000)
15
*/
16
@Before(value = "", order = 10000)
17
public void beforeScenario() { }
18
19
/**
20
* Before hook with Scenario parameter for access to scenario metadata
21
*/
22
@Before
23
public void beforeScenario(Scenario scenario) {
24
String scenarioName = scenario.getName();
25
Collection<String> tags = scenario.getSourceTagNames();
26
}
27
```
28
29
**Usage Examples:**
30
31
```java
32
import io.cucumber.java.Before;
33
import io.cucumber.java.Scenario;
34
35
public class HookDefinitions {
36
37
// Run before every scenario
38
@Before
39
public void setUp() {
40
// Global setup logic
41
}
42
43
// Run only before scenarios tagged with @database
44
@Before("@database")
45
public void setUpDatabase() {
46
// Database-specific setup
47
}
48
49
// Run only before scenarios tagged with @web but not @mobile
50
@Before("@web and not @mobile")
51
public void setUpWebDriver() {
52
// Web driver setup
53
}
54
55
// Run first (order 1) before other setup hooks
56
@Before(order = 1)
57
public void setUpFirst() {
58
// High priority setup
59
}
60
61
// Access scenario information
62
@Before
63
public void beforeWithScenario(Scenario scenario) {
64
System.out.println("Starting scenario: " + scenario.getName());
65
if (scenario.getSourceTagNames().contains("@slow")) {
66
// Special handling for slow tests
67
}
68
}
69
}
70
```
71
72
### After Hook
73
74
Execute method after each scenario with access to scenario results and execution order control.
75
76
```java { .api }
77
/**
78
* Execute method after each scenario
79
* @param value Tag expression for conditional execution (default: "")
80
* @param order Execution order, higher numbers run first (default: 10000)
81
*/
82
@After(value = "", order = 10000)
83
public void afterScenario() { }
84
85
/**
86
* After hook with Scenario parameter for access to results and reporting
87
*/
88
@After
89
public void afterScenario(Scenario scenario) {
90
Status status = scenario.getStatus();
91
boolean failed = scenario.isFailed();
92
}
93
```
94
95
**Usage Examples:**
96
97
```java
98
import io.cucumber.java.After;
99
import io.cucumber.java.Scenario;
100
import io.cucumber.java.Status;
101
102
public class HookDefinitions {
103
104
// Run after every scenario
105
@After
106
public void tearDown() {
107
// Global cleanup logic
108
}
109
110
// Run only after scenarios tagged with @database
111
@After("@database")
112
public void tearDownDatabase() {
113
// Database cleanup
114
}
115
116
// Run last (order 0) after other teardown hooks
117
@After(order = 0)
118
public void tearDownLast() {
119
// Final cleanup
120
}
121
122
// Handle failed scenarios
123
@After
124
public void afterScenario(Scenario scenario) {
125
if (scenario.isFailed()) {
126
// Take screenshot, log error details, etc.
127
scenario.log("Scenario failed: " + scenario.getName());
128
129
// Attach screenshot for failed web tests
130
if (scenario.getSourceTagNames().contains("@web")) {
131
byte[] screenshot = takeScreenshot();
132
scenario.attach(screenshot, "image/png", "Failed Screenshot");
133
}
134
}
135
}
136
137
// Report scenario status
138
@After
139
public void reportStatus(Scenario scenario) {
140
Status status = scenario.getStatus();
141
switch (status) {
142
case PASSED:
143
scenario.log("✓ Test passed successfully");
144
break;
145
case FAILED:
146
scenario.log("✗ Test failed");
147
break;
148
case SKIPPED:
149
scenario.log("○ Test was skipped");
150
break;
151
default:
152
scenario.log("? Test status: " + status);
153
}
154
}
155
}
156
```
157
158
### BeforeStep Hook
159
160
Execute method before each step with optional tag filtering and execution order control.
161
162
```java { .api }
163
/**
164
* Execute method before each step
165
* @param value Tag expression for conditional execution (default: "")
166
* @param order Execution order, lower numbers run first (default: 10000)
167
*/
168
@BeforeStep(value = "", order = 10000)
169
public void beforeStep() { }
170
171
/**
172
* BeforeStep hook with Scenario parameter
173
*/
174
@BeforeStep
175
public void beforeStep(Scenario scenario) {
176
// Access scenario context before each step
177
}
178
```
179
180
**Usage Examples:**
181
182
```java
183
import io.cucumber.java.BeforeStep;
184
import io.cucumber.java.Scenario;
185
186
public class HookDefinitions {
187
188
// Log each step execution
189
@BeforeStep
190
public void logStep(Scenario scenario) {
191
scenario.log("About to execute step in: " + scenario.getName());
192
}
193
194
// Prepare for web steps only
195
@BeforeStep("@web")
196
public void beforeWebStep() {
197
// Web-specific step preparation
198
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
199
}
200
201
// High priority step preparation
202
@BeforeStep(order = 1000)
203
public void prepareStep() {
204
// Critical step preparation
205
}
206
}
207
```
208
209
### AfterStep Hook
210
211
Execute method after each step with access to step results and execution order control.
212
213
```java { .api }
214
/**
215
* Execute method after each step
216
* @param value Tag expression for conditional execution (default: "")
217
* @param order Execution order, higher numbers run first (default: 10000)
218
*/
219
@AfterStep(value = "", order = 10000)
220
public void afterStep() { }
221
222
/**
223
* AfterStep hook with Scenario parameter
224
*/
225
@AfterStep
226
public void afterStep(Scenario scenario) {
227
// Access scenario context after each step
228
}
229
```
230
231
**Usage Examples:**
232
233
```java
234
import io.cucumber.java.AfterStep;
235
import io.cucumber.java.Scenario;
236
237
public class HookDefinitions {
238
239
// Take screenshot after each step in web tests
240
@AfterStep("@web")
241
public void screenshotAfterStep(Scenario scenario) {
242
if (scenario.getSourceTagNames().contains("@screenshot")) {
243
byte[] screenshot = takeScreenshot();
244
scenario.attach(screenshot, "image/png", "Step Screenshot");
245
}
246
}
247
248
// Log step completion
249
@AfterStep
250
public void logStepCompletion(Scenario scenario) {
251
scenario.log("Completed step in: " + scenario.getName());
252
}
253
254
// Cleanup after critical steps
255
@AfterStep("@cleanup")
256
public void cleanupAfterStep() {
257
// Cleanup logic
258
}
259
}
260
```
261
262
### BeforeAll Hook
263
264
Execute static method before all scenarios are executed. These hooks run once per test execution.
265
266
**Note: This annotation is currently experimental and may change in future versions.**
267
268
```java { .api }
269
/**
270
* Execute static method before all scenarios
271
* @param order Execution order, lower numbers run first (default: 10000)
272
* Note: BeforeAll methods must be static and take no parameters
273
* API Status: EXPERIMENTAL
274
*/
275
@BeforeAll(order = 10000)
276
public static void beforeAll() { }
277
```
278
279
**Usage Examples:**
280
281
```java
282
import io.cucumber.java.BeforeAll;
283
284
public class HookDefinitions {
285
286
// Global test suite setup
287
@BeforeAll
288
public static void globalSetup() {
289
// Initialize test environment
290
System.setProperty("test.environment", "integration");
291
292
// Start external services
293
startDatabaseService();
294
startWebServer();
295
}
296
297
// High priority global setup
298
@BeforeAll(order = 1)
299
public static void criticalSetup() {
300
// Critical infrastructure setup
301
loadConfiguration();
302
initializeLogging();
303
}
304
305
// Database preparation
306
@BeforeAll(order = 100)
307
public static void prepareDatabase() {
308
// Setup test database
309
runDatabaseMigrations();
310
seedTestData();
311
}
312
}
313
```
314
315
### AfterAll Hook
316
317
Execute static method after all scenarios have been executed. These hooks run once per test execution.
318
319
**Note: This annotation is currently experimental and may change in future versions.**
320
321
```java { .api }
322
/**
323
* Execute static method after all scenarios
324
* @param order Execution order, higher numbers run first (default: 10000)
325
* Note: AfterAll methods must be static and take no parameters
326
* API Status: EXPERIMENTAL
327
*/
328
@AfterAll(order = 10000)
329
public static void afterAll() { }
330
```
331
332
**Usage Examples:**
333
334
```java
335
import io.cucumber.java.AfterAll;
336
337
public class HookDefinitions {
338
339
// Global test suite cleanup
340
@AfterAll
341
public static void globalCleanup() {
342
// Shutdown external services
343
stopWebServer();
344
stopDatabaseService();
345
346
// Generate reports
347
generateTestReport();
348
}
349
350
// High priority cleanup (runs first)
351
@AfterAll(order = 1000)
352
public static void criticalCleanup() {
353
// Critical cleanup that must happen first
354
flushLogs();
355
closeConnections();
356
}
357
358
// Final cleanup (runs last)
359
@AfterAll(order = 1)
360
public static void finalCleanup() {
361
// Final teardown
362
cleanupTempFiles();
363
resetSystemProperties();
364
}
365
}
366
```
367
368
### Tag Expressions
369
370
All hooks support tag expressions for conditional execution:
371
372
```java
373
// Simple tag
374
@Before("@database")
375
376
// Multiple tags (AND)
377
@Before("@web and @integration")
378
379
// Tag exclusion (NOT)
380
@Before("not @skip")
381
382
// Complex expressions
383
@Before("(@web or @mobile) and not @slow")
384
@After("@database and not (@readonly or @mock)")
385
386
// Tag expressions with parentheses
387
@BeforeStep("(@critical or @important) and not @skip")
388
```
389
390
### Execution Order
391
392
Hook execution order is controlled by the `order` parameter:
393
394
- **Before hooks**: Lower numbers execute first (ascending order)
395
- **After hooks**: Higher numbers execute first (descending order)
396
- **Default order**: 10000
397
- **Multiple hooks with same order**: Execution order is undefined
398
399
```java
400
@Before(order = 1) // Runs first
401
@Before(order = 100) // Runs second
402
@Before // Runs third (default order 10000)
403
@Before(order = 20000) // Runs last
404
405
@After(order = 20000) // Runs first (highest number)
406
@After // Runs second (default order 10000)
407
@After(order = 100) // Runs third
408
@After(order = 1) // Runs last (lowest number)
409
```