0
# Runtime Context
1
2
Access to scenario information, status, and reporting capabilities during test execution. The runtime context provides comprehensive access to scenario metadata, execution status, and powerful reporting features for enhanced test visibility and debugging.
3
4
## Capabilities
5
6
### Scenario Interface
7
8
Provides access to scenario information and reporting capabilities in hooks and step definitions.
9
10
```java { .api }
11
/**
12
* Main scenario interface for accessing test execution context
13
*/
14
public final class Scenario {
15
16
/**
17
* Get all tags associated with this scenario
18
* @return Collection of tag names including '@' prefix
19
*/
20
Collection<String> getSourceTagNames();
21
22
/**
23
* Get current execution status of the scenario
24
* @return Current status (most severe status of executed steps)
25
*/
26
Status getStatus();
27
28
/**
29
* Check if scenario has failed
30
* @return true if status is FAILED
31
*/
32
boolean isFailed();
33
34
/**
35
* Attach binary data to the test report
36
* @param data Binary data (e.g., screenshots, files)
37
* @param mediaType MIME type (e.g., "image/png", "application/json")
38
* @param name Human-readable name for the attachment
39
*/
40
void attach(byte[] data, String mediaType, String name);
41
42
/**
43
* Attach text data to the test report
44
* @param data Text content
45
* @param mediaType MIME type (e.g., "text/plain", "text/html")
46
* @param name Human-readable name for the attachment
47
*/
48
void attach(String data, String mediaType, String name);
49
50
/**
51
* Log text message to the test report
52
* @param text Message to log
53
*/
54
void log(String text);
55
56
/**
57
* Get scenario name from feature file
58
* @return Scenario name
59
*/
60
String getName();
61
62
/**
63
* Get unique identifier for this scenario execution
64
* @return Scenario ID (not stable across executions)
65
*/
66
String getId();
67
68
/**
69
* Get URI of the feature file containing this scenario
70
* @return Feature file URI
71
*/
72
URI getUri();
73
74
/**
75
* Get line number of scenario in feature file
76
* @return Line number (or example row line for scenario outlines)
77
*/
78
Integer getLine();
79
}
80
```
81
82
**Usage Examples:**
83
84
```java
85
import io.cucumber.java.After;
86
import io.cucumber.java.Before;
87
import io.cucumber.java.Scenario;
88
import java.util.Collection;
89
90
public class ScenarioContextExamples {
91
92
@Before
93
public void beforeScenario(Scenario scenario) {
94
// Log scenario start
95
scenario.log("Starting scenario: " + scenario.getName());
96
97
// Check scenario tags for setup decisions
98
Collection<String> tags = scenario.getSourceTagNames();
99
100
if (tags.contains("@database")) {
101
scenario.log("Initializing database for scenario");
102
initializeDatabase();
103
}
104
105
if (tags.contains("@web")) {
106
scenario.log("Starting web driver");
107
startWebDriver();
108
}
109
110
// Log scenario metadata
111
scenario.log("Feature file: " + scenario.getUri());
112
scenario.log("Line number: " + scenario.getLine());
113
scenario.log("Scenario ID: " + scenario.getId());
114
}
115
116
@After
117
public void afterScenario(Scenario scenario) {
118
// Log scenario completion
119
Status status = scenario.getStatus();
120
scenario.log("Scenario completed with status: " + status);
121
122
// Handle failed scenarios
123
if (scenario.isFailed()) {
124
scenario.log("❌ Scenario failed: " + scenario.getName());
125
126
// Take screenshot for web tests
127
if (scenario.getSourceTagNames().contains("@web")) {
128
byte[] screenshot = takeScreenshot();
129
scenario.attach(screenshot, "image/png", "Failure Screenshot");
130
}
131
132
// Attach error logs
133
String errorLog = getErrorLog();
134
scenario.attach(errorLog, "text/plain", "Error Log");
135
136
// Attach system state
137
String systemInfo = getSystemInfo();
138
scenario.attach(systemInfo, "application/json", "System State");
139
} else {
140
scenario.log("✅ Scenario passed successfully");
141
}
142
143
// Cleanup based on tags
144
Collection<String> tags = scenario.getSourceTagNames();
145
if (tags.contains("@cleanup")) {
146
scenario.log("Performing cleanup for @cleanup tag");
147
performCleanup();
148
}
149
}
150
}
151
```
152
153
### Status Enumeration
154
155
Represents the execution status of scenarios and steps.
156
157
```java { .api }
158
/**
159
* Execution status enumeration for scenarios and steps
160
*/
161
public enum Status {
162
163
/** Step/scenario executed successfully */
164
PASSED,
165
166
/** Step/scenario was skipped */
167
SKIPPED,
168
169
/** Step is marked as pending (not yet implemented) */
170
PENDING,
171
172
/** No matching step definition found */
173
UNDEFINED,
174
175
/** Multiple matching step definitions found */
176
AMBIGUOUS,
177
178
/** Step/scenario execution failed */
179
FAILED,
180
181
/** Step was not executed (unused) */
182
UNUSED
183
}
184
```
185
186
**Usage Examples:**
187
188
```java
189
import io.cucumber.java.After;
190
import io.cucumber.java.Status;
191
import io.cucumber.java.Scenario;
192
193
public class StatusHandlingExamples {
194
195
@After
196
public void handleScenarioStatus(Scenario scenario) {
197
Status status = scenario.getStatus();
198
199
switch (status) {
200
case PASSED:
201
scenario.log("✅ All steps passed successfully");
202
recordSuccessMetrics();
203
break;
204
205
case FAILED:
206
scenario.log("❌ One or more steps failed");
207
handleFailure(scenario);
208
break;
209
210
case SKIPPED:
211
scenario.log("⏭️ Scenario was skipped");
212
recordSkippedTest();
213
break;
214
215
case PENDING:
216
scenario.log("⏳ Scenario has pending steps");
217
reportPendingSteps();
218
break;
219
220
case UNDEFINED:
221
scenario.log("❓ Scenario has undefined steps");
222
reportUndefinedSteps();
223
break;
224
225
case AMBIGUOUS:
226
scenario.log("⚠️ Scenario has ambiguous step definitions");
227
reportAmbiguousSteps();
228
break;
229
230
case UNUSED:
231
scenario.log("⭕ Scenario was not executed");
232
break;
233
234
default:
235
scenario.log("❓ Unknown status: " + status);
236
}
237
}
238
239
private void handleFailure(Scenario scenario) {
240
// Specific failure handling
241
scenario.log("Failure details for: " + scenario.getName());
242
243
// Attach debug information
244
String debugInfo = gatherDebugInformation();
245
scenario.attach(debugInfo, "text/plain", "Debug Information");
246
247
// Send failure notification
248
sendFailureNotification(scenario.getName(), scenario.getUri().toString());
249
}
250
}
251
```
252
253
### Attachment and Logging
254
255
Comprehensive reporting capabilities for attaching files, screenshots, and logging information.
256
257
```java { .api }
258
/**
259
* Binary attachment with media type specification
260
*/
261
public void attach(byte[] data, String mediaType, String name);
262
263
/**
264
* Text attachment with media type specification
265
*/
266
public void attach(String data, String mediaType, String name);
267
268
/**
269
* Simple text logging
270
*/
271
public void log(String text);
272
```
273
274
**Usage Examples:**
275
276
```java
277
import io.cucumber.java.After;
278
import io.cucumber.java.AfterStep;
279
import io.cucumber.java.Before;
280
import io.cucumber.java.Scenario;
281
import java.io.File;
282
import java.nio.file.Files;
283
284
public class AttachmentExamples {
285
286
@Before("@web")
287
public void beforeWebScenario(Scenario scenario) {
288
scenario.log("🌐 Starting web scenario: " + scenario.getName());
289
290
// Attach browser configuration
291
String browserConfig = getBrowserConfiguration();
292
scenario.attach(browserConfig, "application/json", "Browser Configuration");
293
}
294
295
@AfterStep("@screenshot")
296
public void takeScreenshotAfterStep(Scenario scenario) {
297
// Take screenshot after each step for visual tests
298
byte[] screenshot = takeScreenshot();
299
scenario.attach(screenshot, "image/png", "Step Screenshot");
300
301
scenario.log("📸 Screenshot captured after step");
302
}
303
304
@After
305
public void attachTestResults(Scenario scenario) {
306
// Always attach test execution log
307
String executionLog = getExecutionLog();
308
scenario.attach(executionLog, "text/plain", "Execution Log");
309
310
if (scenario.isFailed()) {
311
// Attach comprehensive failure information
312
attachFailureDetails(scenario);
313
}
314
315
// Attach performance metrics
316
String performanceData = getPerformanceMetrics();
317
scenario.attach(performanceData, "application/json", "Performance Metrics");
318
}
319
320
private void attachFailureDetails(Scenario scenario) {
321
scenario.log("🔍 Collecting failure details...");
322
323
// Screenshot for UI tests
324
if (scenario.getSourceTagNames().contains("@web")) {
325
byte[] screenshot = takeScreenshot();
326
scenario.attach(screenshot, "image/png", "Failure Screenshot");
327
scenario.log("📸 Failure screenshot captured");
328
}
329
330
// Browser logs for web tests
331
if (scenario.getSourceTagNames().contains("@web")) {
332
String browserLogs = getBrowserLogs();
333
scenario.attach(browserLogs, "text/plain", "Browser Console Logs");
334
}
335
336
// Database state for data tests
337
if (scenario.getSourceTagNames().contains("@database")) {
338
String dbState = getDatabaseState();
339
scenario.attach(dbState, "application/json", "Database State");
340
}
341
342
// API response for integration tests
343
if (scenario.getSourceTagNames().contains("@api")) {
344
String lastResponse = getLastApiResponse();
345
scenario.attach(lastResponse, "application/json", "Last API Response");
346
}
347
348
// System logs
349
String systemLogs = getSystemLogs();
350
scenario.attach(systemLogs, "text/plain", "System Logs");
351
352
// Stack trace
353
String stackTrace = getStackTrace();
354
scenario.attach(stackTrace, "text/plain", "Stack Trace");
355
356
scenario.log("🔍 Failure details collection complete");
357
}
358
359
// Example of attaching various file types
360
public void attachVariousFileTypes(Scenario scenario) {
361
try {
362
// HTML report
363
String htmlReport = generateHtmlReport();
364
scenario.attach(htmlReport, "text/html", "Test Report");
365
366
// JSON data
367
String jsonData = getTestData();
368
scenario.attach(jsonData, "application/json", "Test Data");
369
370
// XML configuration
371
String xmlConfig = getXmlConfiguration();
372
scenario.attach(xmlConfig, "application/xml", "Configuration");
373
374
// CSV data
375
String csvData = getCsvData();
376
scenario.attach(csvData, "text/csv", "Data Export");
377
378
// Binary file
379
File logFile = new File("application.log");
380
if (logFile.exists()) {
381
byte[] logContent = Files.readAllBytes(logFile.toPath());
382
scenario.attach(logContent, "application/octet-stream", "Application Log");
383
}
384
385
// PDF report
386
byte[] pdfReport = generatePdfReport();
387
scenario.attach(pdfReport, "application/pdf", "PDF Report");
388
389
} catch (Exception e) {
390
scenario.log("⚠️ Error attaching files: " + e.getMessage());
391
}
392
}
393
}
394
```
395
396
### Scenario Metadata Access
397
398
Access detailed scenario metadata for conditional logic and reporting.
399
400
```java
401
public class ScenarioMetadataExamples {
402
403
@Before
404
public void analyzeScenario(Scenario scenario) {
405
// Basic metadata
406
String name = scenario.getName();
407
String uri = scenario.getUri().toString();
408
Integer line = scenario.getLine();
409
String id = scenario.getId();
410
411
scenario.log("📋 Scenario Analysis:");
412
scenario.log(" Name: " + name);
413
scenario.log(" File: " + uri);
414
scenario.log(" Line: " + line);
415
scenario.log(" ID: " + id);
416
417
// Tag analysis
418
Collection<String> tags = scenario.getSourceTagNames();
419
scenario.log(" Tags: " + String.join(", ", tags));
420
421
// Conditional setup based on metadata
422
if (name.toLowerCase().contains("slow")) {
423
scenario.log("⏰ Slow test detected - increasing timeouts");
424
increaseTimeouts();
425
}
426
427
if (uri.contains("critical")) {
428
scenario.log("🚨 Critical test - enabling detailed logging");
429
enableDetailedLogging();
430
}
431
432
// Tag-based configuration
433
configureBasedOnTags(scenario, tags);
434
}
435
436
private void configureBasedOnTags(Scenario scenario, Collection<String> tags) {
437
if (tags.contains("@performance")) {
438
scenario.log("⚡ Performance test - starting profiler");
439
startProfiler();
440
}
441
442
if (tags.contains("@security")) {
443
scenario.log("🔒 Security test - enabling security monitoring");
444
enableSecurityMonitoring();
445
}
446
447
if (tags.contains("@integration")) {
448
scenario.log("🔗 Integration test - checking external services");
449
checkExternalServices();
450
}
451
452
if (tags.contains("@smoke")) {
453
scenario.log("💨 Smoke test - using minimal setup");
454
useMinimalSetup();
455
}
456
457
// Environment-specific tags
458
if (tags.contains("@dev-only") && !isDevEnvironment()) {
459
scenario.log("⏭️ Dev-only test in non-dev environment - will skip");
460
}
461
462
if (tags.contains("@prod-safe") && isProdEnvironment()) {
463
scenario.log("✅ Production-safe test in prod environment");
464
}
465
}
466
467
@After
468
public void reportScenarioMetrics(Scenario scenario) {
469
// Create detailed scenario report
470
String report = String.format(
471
"Scenario Execution Report:\n" +
472
" Name: %s\n" +
473
" Status: %s\n" +
474
" File: %s (line %d)\n" +
475
" Tags: %s\n" +
476
" Duration: %d ms\n" +
477
" Steps: %d\n",
478
scenario.getName(),
479
scenario.getStatus(),
480
scenario.getUri(),
481
scenario.getLine(),
482
String.join(", ", scenario.getSourceTagNames()),
483
getExecutionDuration(scenario.getId()),
484
getStepCount(scenario.getId())
485
);
486
487
scenario.attach(report, "text/plain", "Execution Report");
488
scenario.log("📊 Execution report generated");
489
}
490
}
491
```
492
493
### PendingException
494
495
Exception class for marking steps as not yet implemented, commonly used during BDD development.
496
497
```java { .api }
498
/**
499
* Exception to mark steps as pending (not yet implemented)
500
*/
501
public final class PendingException extends RuntimeException {
502
503
/**
504
* Create pending exception with default message "TODO: implement me"
505
*/
506
public PendingException();
507
508
/**
509
* Create pending exception with custom message
510
* @param message Custom message describing what needs to be implemented
511
*/
512
public PendingException(String message);
513
}
514
```
515
516
**Usage Examples:**
517
518
```java
519
import io.cucumber.java.PendingException;
520
import io.cucumber.java.en.*;
521
522
public class PendingStepExamples {
523
524
@Given("the user is logged in")
525
public void the_user_is_logged_in() {
526
// TODO: Implement user login logic
527
throw new PendingException("User login not yet implemented");
528
}
529
530
@When("I perform a complex calculation")
531
public void i_perform_complex_calculation() {
532
// TODO: Implement calculation logic
533
throw new PendingException("Complex calculation algorithm pending");
534
}
535
536
@Then("the result should be accurate")
537
public void the_result_should_be_accurate() {
538
// Placeholder for result validation
539
throw new PendingException();
540
}
541
542
@Given("the external API is available")
543
public void external_api_available() {
544
// TODO: Check API availability
545
throw new PendingException("API availability check not implemented - requires API client setup");
546
}
547
548
// Pattern: Implement step gradually
549
@When("I submit the payment form")
550
public void submit_payment_form() {
551
// Step 1: Form validation (implemented)
552
validatePaymentForm();
553
554
// Step 2: Payment processing (pending)
555
throw new PendingException("Payment processing integration pending - waiting for payment gateway setup");
556
557
// Step 3: Result handling (not reached)
558
// handlePaymentResult();
559
}
560
561
// Pattern: Feature flag for incomplete features
562
@Then("the new feature should be visible")
563
public void new_feature_visible() {
564
if (!isFeatureFlagEnabled("NEW_FEATURE")) {
565
throw new PendingException("New feature behind feature flag - implementation complete but not enabled");
566
}
567
568
// Feature implementation here when enabled
569
validateNewFeature();
570
}
571
}
572
```