ZIO Test SBT integration providing test framework support for running ZIO tests in SBT with the standard SBT test interface
npx @tessl/cli install tessl/maven-dev-zio--zio-test-sbt-sjs1-3@2.1.0ZIO Test SBT provides seamless integration between the ZIO Test framework and SBT (Simple Build Tool), enabling developers to run ZIO-based tests within standard SBT build environments. It implements the standard SBT test interface protocol to bridge ZIO's fiber-based testing model with SBT's test execution framework, supporting cross-platform compilation for JVM, Scala.js, and Scala Native targets.
The package includes platform-specific runners, event handling systems, and distributed execution support for JavaScript and Native platforms, while providing advanced features like signal handling and shared runtime management on the JVM.
build.sbt:
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
libraryDependencies += "dev.zio" %% "zio-test-sbt" % "2.1.19" % Testimport zio.test.sbt._For ZIO Test specs that work with this framework:
import zio.test._
import zio.test.sbt.ZTestFramework
import sbt.testing._For platform-specific implementations:
// JVM platform
import zio.test.sbt.{ZTestRunnerJVM, ZTestTask}
// JavaScript platform
import zio.test.sbt.{ZMasterTestRunnerJS, ZSlaveTestRunnerJS}
// Scala Native platform
import zio.test.sbt.{ZMasterTestRunner, ZSlaveTestRunner}ZIO Test SBT works automatically once configured in your build. SBT will discover and run your ZIO test specs:
// Your test spec
object MySpec extends ZIOSpecDefault {
def spec = suite("MySpec")(
test("simple test") {
assertTrue(1 + 1 == 2)
},
test("async test") {
for {
result <- ZIO.succeed(42)
} yield assertTrue(result == 42)
}
)
}Run tests using standard SBT commands:
sbt test # Run all tests
sbt testOnly MySpec # Run specific test class
sbt testQuick # Run only failed testsZIO Test SBT is built around the SBT test interface architecture:
ZTestFramework implements SBT's Framework interface for test discoveryZioSpecFingerprint tells SBT how to identify ZIO test classesZTestRunnerJVM, ZTestRunnerJS, ZTestRunnerNative) manage test execution lifecycleZTestTask and BaseTestTask execute individual test suites and report resultsZTestEventHandlerSbt and ZTestEvent bridge ZIO test events to SBT's reporting systemCore framework classes that integrate ZIO Test with SBT's test discovery and execution system.
class ZTestFramework extends Framework {
val name: String
val fingerprints: Array[Fingerprint]
def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): Runner
}
object ZioSpecFingerprint extends SubclassFingerprint {
def superclassName(): String
def isModule(): Boolean
def requireNoArgConstructor(): Boolean
}JVM-specific test runner implementation with advanced features like signal handling and shared runtime management.
class ZTestRunnerJVM(
val args: Array[String],
val remoteArgs: Array[String],
testClassLoader: ClassLoader
) extends Runner {
def tasks(defs: Array[TaskDef]): Array[Task]
def done(): String
}
class ZTestTask[T](
taskDef: TaskDef,
testClassLoader: ClassLoader,
sendSummary: SendSummary,
testArgs: TestArgs,
spec: ZIOSpecAbstract,
runtime: zio.Runtime[T],
console: zio.Console
) extends BaseTestTaskJavaScript and Scala Native test runners with distributed execution support for running tests across multiple processes or workers.
// JavaScript Platform
class ZMasterTestRunnerJS(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader
) extends ZTestRunnerJS
class ZSlaveTestRunnerJS(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
sendSummary: SendSummary
) extends ZTestRunnerJS
// Scala Native Platform
class ZMasterTestRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader
) extends ZTestRunnerNative
class ZSlaveTestRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
sendSummary: SendSummary
) extends ZTestRunnerNativeEvent handling system that converts ZIO test events to SBT-compatible events for proper test result reporting and integration.
class ZTestEventHandlerSbt(
eventHandler: EventHandler,
taskDef: TaskDef,
renderer: TestRenderer
) extends ZTestEventHandler {
def handle(event: ExecutionEvent): UIO[Unit]
}
case class ZTestEvent(
fullyQualifiedName0: String,
selector0: Selector,
status0: Status,
maybeThrowable: Option[Throwable],
duration0: Long,
fingerprint0: Fingerprint
) extends Event// Package-level type aliases and utilities
type SendSummary = URIO[Summary, Unit]
object SendSummary {
def fromSend(send: Summary => Unit): SendSummary
def fromSendZIO(send: Summary => UIO[Unit]): SendSummary
def noop: SendSummary
}
// Base test task shared across all platforms
abstract class BaseTestTask(
taskDef0: TaskDef,
val testClassLoader: ClassLoader,
val sendSummary: SendSummary,
val args: TestArgs,
val spec: ZIOSpecAbstract,
val runtime: zio.Runtime[_],
val console: Console
) extends Task {
final def taskDef(): TaskDef = taskDef0
def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[Task]
def tags(): Array[String] = Array.empty
/** Platform-agnostic test execution */
private[zio] def run(eventHandlerZ: ZTestEventHandler): ZIO[Any, Throwable, Unit]
}
// Serialization for cross-platform execution (JS/Native only)
object SummaryProtocol {
/** Serializes Summary to tab-separated string for cross-process communication */
def serialize(summary: Summary): String
/** Deserializes tab-separated string back to Summary */
def deserialize(s: String): Option[Summary]
/** Escapes tab characters in tokens for safe serialization */
private def escape(token: String): String
/** Unescapes tab characters from deserialized tokens */
private def unescape(token: String): String
}