or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cross-platform.mdevent-handling.mdindex.mdsbt-framework.mdtest-runners.md
tile.json

test-runners.mddocs/

Test Runners

This document covers the platform-specific test runners that execute ZIO tests within the SBT ecosystem.

BaseTestTask

The shared base class for all ZIO test tasks across platforms.

abstract class BaseTestTask[T](
  taskDef0: sbt.testing.TaskDef,
  testClassLoader: ClassLoader,
  sendSummary: SendSummary,
  args: zio.test.TestArgs,
  spec: zio.test.ZIOSpecAbstract,
  runtime: zio.Runtime[T],
  console: zio.Console
) extends sbt.testing.Task {
  
  final def taskDef(): sbt.testing.TaskDef
  def execute(eventHandler: sbt.testing.EventHandler, loggers: Array[sbt.testing.Logger]): Array[sbt.testing.Task]
  def tags(): Array[String]
  
  // Protected methods for subclass customization
  protected def sharedFilledTestLayer(implicit trace: zio.Trace): zio.ZLayer[Any, Nothing, zio.test.TestEnvironment with zio.ZIOAppArgs with zio.Scope]
}

Constructor Parameters

  • taskDef0: SBT task definition containing test class information
  • testClassLoader: ClassLoader for loading test classes
  • sendSummary: Function for sending test summaries
  • args: ZIO test arguments and configuration
  • spec: The ZIO test specification to execute
  • runtime: ZIO runtime for test execution
  • console: Console implementation for test output

Methods

taskDef

Returns the SBT task definition.

baseTask.taskDef()
// Returns: sbt.testing.TaskDef

execute

Executes the test task and returns any subtasks.

Parameters:

  • eventHandler: SBT event handler for test result reporting
  • loggers: Array of SBT loggers for output

Returns: Array of additional tasks (typically empty)

tags

Returns task tags for SBT categorization.

baseTask.tags()
// Returns: Array[String] (empty array)

JVM Test Runner

The full-featured JVM test runner with advanced capabilities.

final class ZTestRunnerJVM(
  val args: Array[String],
  val remoteArgs: Array[String], 
  testClassLoader: ClassLoader
) extends sbt.testing.Runner {
  
  var renderer: zio.test.render.TestRenderer
  var shutdownHook: Option[() => Unit]
  val summaries: java.util.concurrent.atomic.AtomicReference[Vector[zio.test.Summary]]
  
  def sendSummary(implicit trace: zio.Trace): SendSummary
  def done(): String
  def tasks(defs: Array[sbt.testing.TaskDef]): Array[sbt.testing.Task]
  def tasksZ(defs: Array[sbt.testing.TaskDef], console: zio.Console)(implicit trace: zio.Trace): Array[ZTestTask[zio.test.TestOutput]]
}

Properties

  • renderer: Configurable test output renderer (default: ConsoleRenderer)
  • shutdownHook: Optional cleanup function executed when tests complete
  • summaries: Thread-safe collection of test summaries from all executed tasks

Methods

sendSummary

Creates a summary sender that collects results for final reporting.

implicit val trace: zio.Trace = zio.Trace.empty
val sender = runner.sendSummary
// Returns: SendSummary

done

Completes test execution and returns formatted summary.

val result = runner.done()
// Returns: String with formatted test results

Behavior:

  • Aggregates all collected summaries
  • Renders final results using the configured renderer
  • Prints results directly to console (workaround for SBT forked JVM bug)
  • Executes shutdown hooks for cleanup

tasks

Creates SBT tasks from task definitions.

val tasks = runner.tasks(taskDefs)
// Returns: Array[sbt.testing.Task]

tasksZ

ZIO-native version of task creation with enhanced configuration.

Parameters:

  • defs: Array of SBT task definitions
  • console: ZIO Console implementation

Returns: Array of ZTestTask[TestOutput] with shared runtime and layers

JVM ZTestTask

Enhanced task implementation with signal handling.

final class ZTestTask[T](
  taskDef: sbt.testing.TaskDef,
  testClassLoader: ClassLoader,
  sendSummary: SendSummary,
  testArgs: zio.test.TestArgs,
  spec: zio.test.ZIOSpecAbstract,
  runtime: zio.Runtime[T],
  console: zio.Console
) extends BaseTestTask(taskDef, testClassLoader, sendSummary, testArgs, spec, runtime, console)

Signal Handling

The JVM implementation includes signal handlers for debugging:

// Install handlers for fiber dumping
// Windows: SIGINT (Ctrl+C)
// Unix: SIGINFO, SIGUSR1
private def installSignalHandlers(): Unit

JavaScript Test Runners

JavaScript platform runners support distributed testing patterns.

Master Runner

final class ZMasterTestRunnerJS(
  args: Array[String],
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "master")

Used for single-process test execution.

Slave Runner

final class ZSlaveTestRunnerJS(
  args: Array[String],
  remoteArgs: Array[String],
  testClassLoader: ClassLoader,
  sendSummary: SendSummary
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "slave")

Used in distributed testing scenarios with custom summary handling.

Base JavaScript Runner

sealed abstract class ZTestRunnerJS(
  val args: Array[String],
  val remoteArgs: Array[String],
  testClassLoader: ClassLoader,
  runnerType: String
) extends sbt.testing.Runner {
  
  def sendSummary: SendSummary
  val summaries: scala.collection.mutable.Buffer[zio.test.Summary]
  
  def done(): String
  def tasks(defs: Array[sbt.testing.TaskDef]): Array[sbt.testing.Task]
  def receiveMessage(summary: String): Option[String]
  def serializeTask(task: sbt.testing.Task, serializer: sbt.testing.TaskDef => String): String
  def deserializeTask(task: String, deserializer: String => sbt.testing.TaskDef): sbt.testing.Task
}

Native Test Runners

Native platform runners with optimized concurrency primitives.

Master Runner

final class ZMasterTestRunner(
  args: Array[String],
  remoteArgs: Array[String],
  testClassLoader: ClassLoader
) extends ZTestRunnerNative(args, remoteArgs, testClassLoader, "master")

Slave Runner

final class ZSlaveTestRunner(
  args: Array[String],
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader,
  sendSummary: SendSummary
) extends ZTestRunnerNative(args, remoteArgs, testClassLoader, "slave")

Base Native Runner

sealed abstract class ZTestRunnerNative(
  val args: Array[String],
  remoteArgs0: Array[String],
  testClassLoader: ClassLoader,
  runnerType: String
) extends sbt.testing.Runner {
  
  def remoteArgs(): Array[String]
  def sendSummary: SendSummary
  val summaries: java.util.concurrent.ConcurrentLinkedQueue[zio.test.Summary]
  
  def done(): String
  def tasks(defs: Array[sbt.testing.TaskDef]): Array[sbt.testing.Task]
  def receiveMessage(summary: String): Option[String]
  def serializeTask(task: sbt.testing.Task, serializer: sbt.testing.TaskDef => String): String
  def deserializeTask(task: String, deserializer: String => sbt.testing.TaskDef): sbt.testing.Task
}

Usage Examples

Creating Custom Runners

import zio.test.sbt._

// JVM runner with custom configuration
val jvmRunner = new ZTestRunnerJVM(
  args = Array("--testSearchTerms", "MyTest"),
  remoteArgs = Array(),
  testClassLoader = getClass.getClassLoader
)

// Configure custom renderer
jvmRunner.renderer = zio.test.render.LogAnnotationRenderer()

// Add shutdown hook
jvmRunner.shutdownHook = Some(() => println("Tests completed"))

Task Execution

// Create tasks from test definitions
val tasks = runner.tasks(taskDefs)

// Execute tasks with event handling
val eventHandler: sbt.testing.EventHandler = ???
val loggers: Array[sbt.testing.Logger] = Array()

tasks.foreach { task =>
  val subtasks = task.execute(eventHandler, loggers)
  // Process any returned subtasks
}

// Get final results
val summary = runner.done()
println(summary)

Cross-Platform Runner Selection

// Platform-specific runner creation
val runner = scala.util.Properties.isJavaAtLeastVersion("1.8") match {
  case true => new ZTestRunnerJVM(args, remoteArgs, classLoader)
  case false => ??? // Handle other platforms
}