or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cross-platform-execution.mdevent-handling.mdframework-integration.mdindex.mdjvm-execution.md
tile.json

event-handling.mddocs/

Event Handling and Reporting

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.

Capabilities

ZTestEventHandlerSbt

Thread-safe event handler that processes ZIO test execution events and reports them to SBT's event handling system.

/**
 * Handles ZIO test events and reports them to SBT
 * Extends ZTestEventHandler for ZIO Test integration
 */
class ZTestEventHandlerSbt(
  eventHandler: EventHandler,
  taskDef: TaskDef,
  renderer: TestRenderer
) extends ZTestEventHandler {
  /** Semaphore for thread-safe event handling (initialized with permit count 1) */
  val semaphore: Semaphore = Semaphore.unsafe.make(1L)(Unsafe.unsafe)
  
  /** Processes ZIO execution events and converts them to SBT events */
  def handle(event: ExecutionEvent): UIO[Unit]
}

The handler processes different types of ZIO test events:

  • TestStarted: Test execution beginning (currently no-op)
  • Test: Individual test completion with results
  • SectionStart/SectionEnd: Test suite organization events (no-op)
  • TopLevelFlush: Test output synchronization (no-op)
  • RuntimeFailure: Catastrophic test failures

Usage Example:

// Created automatically by test tasks
val eventHandler = new ZTestEventHandlerSbt(sbtEventHandler, taskDef, renderer)

// Processes events during test execution
eventHandler.handle(ExecutionEvent.Test(...))  // Converts to SBT event

ZTestEvent

SBT-compatible test event that wraps ZIO test results in the format expected by SBT's reporting system.

/**
 * SBT-compatible test event representation
 * Implements sbt.testing.Event interface
 */
case class ZTestEvent(
  fullyQualifiedName0: String,
  selector0: Selector,
  status0: Status,
  maybeThrowable: Option[Throwable],
  duration0: Long,
  fingerprint0: Fingerprint
) extends Event {
  /** Test execution duration in milliseconds */
  def duration(): Long = duration0
  
  /** Test fingerprint for SBT integration */
  def fingerprint(): Fingerprint = fingerprint0
  
  /** Fully qualified test class name */
  def fullyQualifiedName(): String = fullyQualifiedName0
  
  /** Test selector identifying specific test */
  def selector(): Selector = selector0
  
  /** Test execution status (Success, Failure, Ignored, etc.) */
  def status(): Status = status0
  
  /** Optional exception for test failures */
  def throwable(): OptionalThrowable
}

Event Conversion

The ZTestEvent companion object provides utilities for converting ZIO test events to SBT events.

/**
 * Companion object with event conversion utilities
 */
object ZTestEvent {
  /** 
   * Converts ZIO ExecutionEvent.Test to SBT Event
   * Includes failure message rendering and status mapping
   */
  def convertEvent(
    test: ExecutionEvent.Test[_],
    taskDef: TaskDef, 
    renderer: TestRenderer
  ): Event
  
  /** Maps ZIO test results to SBT status codes */
  private def statusFrom(test: ExecutionEvent.Test[_]): Status = {
    test.test match {
      case Left(_) => Status.Failure
      case Right(value) =>
        value match {
          case TestSuccess.Succeeded(_) => Status.Success
          case TestSuccess.Ignored(_)   => Status.Ignored
        }
    }
  }
}

Status Mapping:

ZIO Test ResultSBT Status
TestSuccess.SucceededStatus.Success
TestSuccess.IgnoredStatus.Ignored
Left(failure)Status.Failure

Usage Example:

// Automatic conversion during event handling
val zioTestEvent = ExecutionEvent.Test(...)
val sbtEvent = ZTestEvent.convertEvent(zioTestEvent, taskDef, renderer)
sbtEventHandler.handle(sbtEvent)

Failure Reporting

When tests fail, the event handler creates detailed failure reports using the configured renderer.

// Failure handling in ZTestEventHandlerSbt.handle()
case evt @ ExecutionEvent.Test(_, _, _, _, _, _, _) =>
  val zTestEvent = ZTestEvent.convertEvent(evt, taskDef, renderer)
  semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
  // For failures, includes rendered failure message as exception
  // The convertEvent method automatically creates exception with failure details

Failure Message Contents:

  • Test name and location
  • Expected vs actual values
  • Stack traces for exceptions
  • ANSI color formatting for console output
  • Assertion details and context

Runtime Failure Handling

The event handler also processes runtime failures that occur outside of individual tests.

case ExecutionEvent.RuntimeFailure(_, _, failure, _) =>
  failure match {
    case TestFailure.Assertion(_, _) => 
      ZIO.unit  // Assertion failures come through ExecutionEvent.Test path
      
    case TestFailure.Runtime(cause, annotations) =>
      val zTestEvent = ZTestEvent(
        taskDef.fullyQualifiedName(),
        taskDef.selectors().head,
        Status.Failure,
        cause.dieOption,  // Extract throwable from ZIO Cause
        annotations.get(TestAnnotation.timing).toMillis,
        ZioSpecFingerprint
      )
      // Report runtime failure to SBT with thread-safe handling
      semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
  }

Thread Safety

All event handling is thread-safe through the use of semaphores to serialize access to SBT's event handler.

// Thread-safe event reporting
val semaphore = Semaphore.unsafe.make(1L)

def handle(event: ExecutionEvent): UIO[Unit] = {
  val zTestEvent = ZTestEvent.convertEvent(event, taskDef, renderer)
  // Serialize access to SBT event handler
  semaphore.withPermit(ZIO.succeed(eventHandler.handle(zTestEvent)))
}

This ensures that multiple concurrent tests don't interfere with each other when reporting results to SBT.

Integration with Build Tools

The event handling system ensures proper integration with various build tools and IDEs:

SBT Integration:

  • Test results appear in SBT console with proper formatting
  • Failed tests are marked with detailed error messages
  • Test timing information is preserved
  • Test filtering and selection works correctly

IDE Integration:

  • IntelliJ IDEA, VS Code, and other IDEs receive proper test events
  • Test explorer shows individual test results
  • Failed tests are highlighted with failure details
  • Click-to-navigate works for test failures

CI/CD Integration:

  • JUnit XML output (when enabled) includes all test results
  • Test summaries are properly aggregated
  • Build failures occur when tests fail
  • Test timing and parallelization data is available

Event Processing Flow

  1. ZIO Test Execution: Tests run within ZIO fiber context
  2. Event Generation: ZIO Test generates ExecutionEvent instances
  3. Event Handling: ZTestEventHandlerSbt receives and processes events
  4. Event Conversion: ZIO events converted to SBT Event instances
  5. SBT Reporting: Converted events sent to SBT's event handler
  6. Build Integration: SBT integrates events with build system and tools