0
# Event Handling and Reporting
1
2
Event handling system that converts ZIO test events to SBT-compatible events for proper test result reporting and integration. This system ensures that ZIO test results are correctly reported to SBT and integrated with build tools and IDEs.
3
4
## Capabilities
5
6
### ZTestEventHandlerSbt
7
8
Thread-safe event handler that processes ZIO test execution events and reports them to SBT's event handling system.
9
10
```scala { .api }
11
/**
12
* Handles ZIO test events and reports them to SBT
13
* Extends ZTestEventHandler for ZIO Test integration
14
*/
15
class ZTestEventHandlerSbt(
16
eventHandler: EventHandler,
17
taskDef: TaskDef,
18
renderer: TestRenderer
19
) extends ZTestEventHandler {
20
/** Semaphore for thread-safe event handling (initialized with permit count 1) */
21
val semaphore: Semaphore = Semaphore.unsafe.make(1L)(Unsafe.unsafe)
22
23
/** Processes ZIO execution events and converts them to SBT events */
24
def handle(event: ExecutionEvent): UIO[Unit]
25
}
26
```
27
28
The handler processes different types of ZIO test events:
29
30
- **TestStarted**: Test execution beginning (currently no-op)
31
- **Test**: Individual test completion with results
32
- **SectionStart/SectionEnd**: Test suite organization events (no-op)
33
- **TopLevelFlush**: Test output synchronization (no-op)
34
- **RuntimeFailure**: Catastrophic test failures
35
36
**Usage Example:**
37
38
```scala
39
// Created automatically by test tasks
40
val eventHandler = new ZTestEventHandlerSbt(sbtEventHandler, taskDef, renderer)
41
42
// Processes events during test execution
43
eventHandler.handle(ExecutionEvent.Test(...)) // Converts to SBT event
44
```
45
46
### ZTestEvent
47
48
SBT-compatible test event that wraps ZIO test results in the format expected by SBT's reporting system.
49
50
```scala { .api }
51
/**
52
* SBT-compatible test event representation
53
* Implements sbt.testing.Event interface
54
*/
55
case class ZTestEvent(
56
fullyQualifiedName0: String,
57
selector0: Selector,
58
status0: Status,
59
maybeThrowable: Option[Throwable],
60
duration0: Long,
61
fingerprint0: Fingerprint
62
) extends Event {
63
/** Test execution duration in milliseconds */
64
def duration(): Long = duration0
65
66
/** Test fingerprint for SBT integration */
67
def fingerprint(): Fingerprint = fingerprint0
68
69
/** Fully qualified test class name */
70
def fullyQualifiedName(): String = fullyQualifiedName0
71
72
/** Test selector identifying specific test */
73
def selector(): Selector = selector0
74
75
/** Test execution status (Success, Failure, Ignored, etc.) */
76
def status(): Status = status0
77
78
/** Optional exception for test failures */
79
def throwable(): OptionalThrowable
80
}
81
```
82
83
### Event Conversion
84
85
The `ZTestEvent` companion object provides utilities for converting ZIO test events to SBT events.
86
87
```scala { .api }
88
/**
89
* Companion object with event conversion utilities
90
*/
91
object ZTestEvent {
92
/**
93
* Converts ZIO ExecutionEvent.Test to SBT Event
94
* Includes failure message rendering and status mapping
95
*/
96
def convertEvent(
97
test: ExecutionEvent.Test[_],
98
taskDef: TaskDef,
99
renderer: TestRenderer
100
): Event
101
102
/** Maps ZIO test results to SBT status codes */
103
private def statusFrom(test: ExecutionEvent.Test[_]): Status = {
104
test.test match {
105
case Left(_) => Status.Failure
106
case Right(value) =>
107
value match {
108
case TestSuccess.Succeeded(_) => Status.Success
109
case TestSuccess.Ignored(_) => Status.Ignored
110
}
111
}
112
}
113
}
114
```
115
116
**Status Mapping:**
117
118
| ZIO Test Result | SBT Status |
119
|----------------|------------|
120
| `TestSuccess.Succeeded` | `Status.Success` |
121
| `TestSuccess.Ignored` | `Status.Ignored` |
122
| `Left(failure)` | `Status.Failure` |
123
124
**Usage Example:**
125
126
```scala
127
// Automatic conversion during event handling
128
val zioTestEvent = ExecutionEvent.Test(...)
129
val sbtEvent = ZTestEvent.convertEvent(zioTestEvent, taskDef, renderer)
130
sbtEventHandler.handle(sbtEvent)
131
```
132
133
### Failure Reporting
134
135
When tests fail, the event handler creates detailed failure reports using the configured renderer.
136
137
```scala { .api }
138
// Failure handling in ZTestEventHandlerSbt.handle()
139
case evt @ ExecutionEvent.Test(_, _, _, _, _, _, _) =>
140
val zTestEvent = ZTestEvent.convertEvent(evt, taskDef, renderer)
141
semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
142
// For failures, includes rendered failure message as exception
143
// The convertEvent method automatically creates exception with failure details
144
```
145
146
**Failure Message Contents:**
147
148
- Test name and location
149
- Expected vs actual values
150
- Stack traces for exceptions
151
- ANSI color formatting for console output
152
- Assertion details and context
153
154
### Runtime Failure Handling
155
156
The event handler also processes runtime failures that occur outside of individual tests.
157
158
```scala { .api }
159
case ExecutionEvent.RuntimeFailure(_, _, failure, _) =>
160
failure match {
161
case TestFailure.Assertion(_, _) =>
162
ZIO.unit // Assertion failures come through ExecutionEvent.Test path
163
164
case TestFailure.Runtime(cause, annotations) =>
165
val zTestEvent = ZTestEvent(
166
taskDef.fullyQualifiedName(),
167
taskDef.selectors().head,
168
Status.Failure,
169
cause.dieOption, // Extract throwable from ZIO Cause
170
annotations.get(TestAnnotation.timing).toMillis,
171
ZioSpecFingerprint
172
)
173
// Report runtime failure to SBT with thread-safe handling
174
semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
175
}
176
```
177
178
### Thread Safety
179
180
All event handling is thread-safe through the use of semaphores to serialize access to SBT's event handler.
181
182
```scala { .api }
183
// Thread-safe event reporting
184
val semaphore = Semaphore.unsafe.make(1L)
185
186
def handle(event: ExecutionEvent): UIO[Unit] = {
187
val zTestEvent = ZTestEvent.convertEvent(event, taskDef, renderer)
188
// Serialize access to SBT event handler
189
semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
190
}
191
```
192
193
This ensures that multiple concurrent tests don't interfere with each other when reporting results to SBT.
194
195
### Integration with Build Tools
196
197
The event handling system ensures proper integration with various build tools and IDEs:
198
199
**SBT Integration:**
200
- Test results appear in SBT console with proper formatting
201
- Failed tests are marked with detailed error messages
202
- Test timing information is preserved
203
- Test filtering and selection works correctly
204
205
**IDE Integration:**
206
- IntelliJ IDEA, VS Code, and other IDEs receive proper test events
207
- Test explorer shows individual test results
208
- Failed tests are highlighted with failure details
209
- Click-to-navigate works for test failures
210
211
**CI/CD Integration:**
212
- JUnit XML output (when enabled) includes all test results
213
- Test summaries are properly aggregated
214
- Build failures occur when tests fail
215
- Test timing and parallelization data is available
216
217
### Event Processing Flow
218
219
1. **ZIO Test Execution**: Tests run within ZIO fiber context
220
2. **Event Generation**: ZIO Test generates `ExecutionEvent` instances
221
3. **Event Handling**: `ZTestEventHandlerSbt` receives and processes events
222
4. **Event Conversion**: ZIO events converted to SBT `Event` instances
223
5. **SBT Reporting**: Converted events sent to SBT's event handler
224
6. **Build Integration**: SBT integrates events with build system and tools