0
# Test Context
1
2
Test execution context and utilities providing access to scenario metadata, status information, and reporting capabilities. Includes the Scenario class for runtime test information and PendingException for marking unimplemented steps.
3
4
## Capabilities
5
6
### Scenario Class
7
8
Provides comprehensive access to test execution context, including scenario metadata, status information, and attachment/logging utilities for test reporting.
9
10
```java { .api }
11
/**
12
* Scenario context providing test execution information and reporting utilities
13
* Available in hooks and accessible through test framework integration
14
*/
15
public final class Scenario {
16
/**
17
* Get all tags associated with this scenario
18
* @return Collection of tag names including '@' prefix (e.g., "@web", "@smoke")
19
*/
20
public Collection<String> getSourceTagNames() { ... }
21
22
/**
23
* Get current execution status of the scenario
24
* @return Current status (PASSED, FAILED, SKIPPED, etc.)
25
*/
26
public Status getStatus() { ... }
27
28
/**
29
* Check if the scenario has failed
30
* @return true if scenario status is FAILED, false otherwise
31
*/
32
public boolean isFailed() { ... }
33
34
/**
35
* Attach binary data to the test report
36
* @param data Binary data to attach
37
* @param mediaType MIME type of the data (e.g., "image/png", "application/json")
38
* @param name Descriptive name for the attachment
39
*/
40
public void attach(byte[] data, String mediaType, String name) { ... }
41
42
/**
43
* Attach text data to the test report
44
* @param data Text data to attach
45
* @param mediaType MIME type of the text (e.g., "text/plain", "application/json")
46
* @param name Descriptive name for the attachment
47
*/
48
public void attach(String data, String mediaType, String name) { ... }
49
50
/**
51
* Log text message to the test report
52
* @param text Message to log for debugging and reporting
53
*/
54
public void log(String text) { ... }
55
56
/**
57
* Get the scenario name as defined in the feature file
58
* @return Scenario name string
59
*/
60
public String getName() { ... }
61
62
/**
63
* Get unique identifier for this scenario
64
* @return Scenario ID string
65
*/
66
public String getId() { ... }
67
68
/**
69
* Get URI of the feature file containing this scenario
70
* @return URI of the feature file
71
*/
72
public URI getUri() { ... }
73
74
/**
75
* Get line number where scenario is defined in the feature file
76
* @return Line number (1-based) or null if not available
77
*/
78
public Integer getLine() { ... }
79
}
80
```
81
82
**Usage Examples:**
83
84
```java
85
import io.cucumber.java8.En;
86
import io.cucumber.java8.Scenario;
87
88
public class ScenarioContextSteps implements En {
89
90
public ScenarioContextSteps() {
91
Before((Scenario scenario) -> {
92
// Log scenario start with metadata
93
scenario.log("Starting scenario: " + scenario.getName());
94
scenario.log("Tags: " + scenario.getSourceTagNames());
95
scenario.log("Location: " + scenario.getUri() + ":" + scenario.getLine());
96
97
// Conditional setup based on tags
98
if (scenario.getSourceTagNames().contains("@database")) {
99
setupDatabaseConnection();
100
}
101
102
if (scenario.getSourceTagNames().contains("@web")) {
103
initializeWebDriver();
104
}
105
});
106
107
After((Scenario scenario) -> {
108
// Capture failure information
109
if (scenario.isFailed()) {
110
scenario.log("Scenario failed with status: " + scenario.getStatus());
111
112
// Attach screenshot for web tests
113
if (webDriver != null) {
114
byte[] screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
115
scenario.attach(screenshot, "image/png", "failure-screenshot");
116
}
117
118
// Attach application logs
119
String logs = getApplicationLogs();
120
scenario.attach(logs, "text/plain", "application-logs");
121
122
// Attach database state for database tests
123
if (scenario.getSourceTagNames().contains("@database")) {
124
String dbState = getDatabaseState();
125
scenario.attach(dbState, "application/json", "database-state");
126
}
127
}
128
129
// Always attach performance metrics
130
String metrics = getPerformanceMetrics();
131
scenario.attach(metrics, "application/json", "performance-metrics");
132
});
133
134
// Step-level logging
135
AfterStep((Scenario scenario) -> {
136
long stepDuration = getLastStepDuration();
137
scenario.log("Step completed in " + stepDuration + "ms");
138
139
// Attach step-specific data for debugging
140
if (scenario.getSourceTagNames().contains("@debug")) {
141
String stepContext = getCurrentStepContext();
142
scenario.attach(stepContext, "application/json", "step-context");
143
}
144
});
145
}
146
}
147
```
148
149
### Status Enum
150
151
Enumeration of possible test execution states providing comprehensive status information.
152
153
```java { .api }
154
/**
155
* Test execution status values
156
*/
157
public enum Status {
158
/** Test executed successfully without failures */
159
PASSED,
160
161
/** Test was skipped during execution */
162
SKIPPED,
163
164
/** Test step is marked as pending (not yet implemented) */
165
PENDING,
166
167
/** Test step has no matching step definition */
168
UNDEFINED,
169
170
/** Test step matches multiple step definitions ambiguously */
171
AMBIGUOUS,
172
173
/** Test execution failed due to assertion failure or exception */
174
FAILED,
175
176
/** Test step was not executed (unused in scenario) */
177
UNUSED
178
}
179
```
180
181
**Usage Examples:**
182
183
```java
184
public class StatusHandlingSteps implements En {
185
186
public StatusHandlingSteps() {
187
After((Scenario scenario) -> {
188
switch (scenario.getStatus()) {
189
case PASSED:
190
scenario.log("✅ Scenario completed successfully");
191
recordSuccessMetrics(scenario);
192
break;
193
194
case FAILED:
195
scenario.log("❌ Scenario failed - investigating...");
196
investigateFailure(scenario);
197
notifyFailureMonitoring(scenario);
198
break;
199
200
case SKIPPED:
201
scenario.log("⏭️ Scenario was skipped");
202
recordSkipReason(scenario);
203
break;
204
205
case PENDING:
206
scenario.log("⏳ Scenario has pending steps");
207
addToPendingBacklog(scenario);
208
break;
209
210
case UNDEFINED:
211
scenario.log("❓ Scenario has undefined steps");
212
generateStepDefinitionTemplates(scenario);
213
break;
214
215
case AMBIGUOUS:
216
scenario.log("🤔 Scenario has ambiguous step definitions");
217
analyzeStepDefinitionConflicts(scenario);
218
break;
219
220
case UNUSED:
221
scenario.log("🚫 Scenario step was not used");
222
break;
223
224
default:
225
scenario.log("Unknown status: " + scenario.getStatus());
226
}
227
});
228
}
229
}
230
```
231
232
### PendingException
233
234
Exception class for marking test steps as not yet implemented, causing tests to be marked with PENDING status instead of failing.
235
236
```java { .api }
237
/**
238
* Exception to mark steps as pending implementation
239
* Thrown from step definitions to indicate the step is not yet implemented
240
* Results in PENDING status rather than FAILED
241
*/
242
public final class PendingException extends RuntimeException {
243
/**
244
* Create pending exception with default message
245
* Default message: "TODO: implement me"
246
*/
247
public PendingException() { ... }
248
249
/**
250
* Create pending exception with custom message
251
* @param message Custom message describing what needs to be implemented
252
*/
253
public PendingException(String message) { ... }
254
}
255
```
256
257
**Usage Examples:**
258
259
```java
260
public class PendingStepDefinitions implements En {
261
262
public PendingStepDefinitions() {
263
// Step not yet implemented - default message
264
Given("a complex integration scenario", () -> {
265
throw new PendingException();
266
// Results in: "TODO: implement me"
267
});
268
269
// Step not yet implemented - custom message
270
When("I perform advanced data processing", () -> {
271
throw new PendingException("Waiting for data processing service API to be finalized");
272
});
273
274
// Conditional pending implementation
275
Then("the advanced analytics should be calculated", () -> {
276
if (!isAdvancedAnalyticsFeatureEnabled()) {
277
throw new PendingException("Advanced analytics feature not yet enabled in test environment");
278
}
279
280
// Normal implementation when feature is enabled
281
verifyAdvancedAnalytics();
282
});
283
284
// Partial implementation with pending parts
285
When("I configure the system with {string}", (String configType) -> {
286
switch (configType) {
287
case "basic":
288
configureBasicSettings();
289
break;
290
case "advanced":
291
throw new PendingException("Advanced configuration not yet implemented");
292
case "enterprise":
293
throw new PendingException("Enterprise configuration pending security review");
294
default:
295
throw new IllegalArgumentException("Unknown config type: " + configType);
296
}
297
});
298
299
// Pending with detailed task breakdown
300
Given("a complete e-commerce checkout flow", () -> {
301
throw new PendingException(
302
"E-commerce checkout implementation pending:\n" +
303
"- Payment gateway integration\n" +
304
"- Inventory reservation\n" +
305
"- Order confirmation email\n" +
306
"- Receipt generation"
307
);
308
});
309
}
310
}
311
```
312
313
### Test Reporting and Attachments
314
315
Comprehensive examples of using Scenario for test reporting, debugging, and evidence collection.
316
317
**Binary Attachments:**
318
319
```java
320
public class AttachmentSteps implements En {
321
322
public AttachmentSteps() {
323
After((Scenario scenario) -> {
324
// Screenshot attachment
325
if (webDriver != null) {
326
byte[] screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
327
scenario.attach(screenshot, "image/png", "final-screenshot");
328
}
329
330
// PDF report attachment
331
byte[] pdfReport = generateTestReport(scenario);
332
scenario.attach(pdfReport, "application/pdf", "test-report");
333
334
// Network capture attachment
335
if (scenario.getSourceTagNames().contains("@network")) {
336
byte[] networkLog = getNetworkCapture();
337
scenario.attach(networkLog, "application/json", "network-capture");
338
}
339
});
340
341
// Step-level binary attachments
342
When("I upload a file", () -> {
343
byte[] uploadedFile = performFileUpload();
344
scenario.attach(uploadedFile, "application/octet-stream", "uploaded-file");
345
});
346
}
347
}
348
```
349
350
**Text and Structured Data Attachments:**
351
352
```java
353
public class TextAttachmentSteps implements En {
354
355
public TextAttachmentSteps() {
356
After((Scenario scenario) -> {
357
// JSON data attachment
358
String apiResponses = collectApiResponses();
359
scenario.attach(apiResponses, "application/json", "api-responses");
360
361
// Plain text logs
362
String applicationLogs = getApplicationLogs();
363
scenario.attach(applicationLogs, "text/plain", "application-logs");
364
365
// CSV data attachment
366
String csvData = generateCsvReport();
367
scenario.attach(csvData, "text/csv", "test-data-report");
368
369
// XML configuration
370
String xmlConfig = getCurrentConfiguration();
371
scenario.attach(xmlConfig, "application/xml", "runtime-configuration");
372
373
// HTML summary
374
String htmlSummary = generateHtmlSummary(scenario);
375
scenario.attach(htmlSummary, "text/html", "test-summary");
376
});
377
}
378
}
379
```
380
381
**Conditional Logging and Attachments:**
382
383
```java
384
public class ConditionalReportingSteps implements En {
385
386
public ConditionalReportingSteps() {
387
After((Scenario scenario) -> {
388
// Tag-based conditional reporting
389
if (scenario.getSourceTagNames().contains("@performance")) {
390
String performanceMetrics = getPerformanceMetrics();
391
scenario.attach(performanceMetrics, "application/json", "performance-metrics");
392
scenario.log("Performance test completed - see attached metrics");
393
}
394
395
if (scenario.getSourceTagNames().contains("@security")) {
396
String securityAudit = getSecurityAuditResults();
397
scenario.attach(securityAudit, "application/json", "security-audit");
398
}
399
400
// Status-based conditional reporting
401
if (scenario.isFailed()) {
402
String debugInfo = collectDebugInformation();
403
scenario.attach(debugInfo, "text/plain", "debug-information");
404
405
String systemState = captureSystemState();
406
scenario.attach(systemState, "application/json", "system-state");
407
408
scenario.log("Failure occurred - debug information and system state captured");
409
}
410
411
// Scenario name-based conditional reporting
412
if (scenario.getName().contains("integration")) {
413
String integrationLogs = getIntegrationLogs();
414
scenario.attach(integrationLogs, "text/plain", "integration-logs");
415
}
416
});
417
}
418
}
419
```