This document covers ZIO Test SBT's implementation of the SBT test framework interface, including test discovery and framework registration.
The main framework class that SBT uses to integrate with ZIO tests.
class ZTestFramework extends sbt.testing.Framework {
val name: String
val fingerprints: Array[sbt.testing.Fingerprint]
def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): sbt.testing.Runner
}name: Returns the framework display name "ZIO Test" with ANSI formattingfingerprints: Array containing ZioSpecFingerprint for test discoveryCreates platform-appropriate test runners:
ZTestRunnerJVM instanceZMasterTestRunnerJS instanceZMasterTestRunner instanceParameters:
args: Command-line arguments passed to the test frameworkremoteArgs: Arguments for remote test execution (distributed testing)testClassLoader: ClassLoader for loading test classesEnables SBT to discover ZIO test classes by identifying ZIOSpecAbstract subclasses.
object ZioSpecFingerprint extends sbt.testing.SubclassFingerprint {
def superclassName(): String
def isModule(): Boolean
def requireNoArgConstructor(): Boolean
}Returns the fully qualified name of the base class that SBT should look for: zio.test.ZIOSpecAbstract.
ZioSpecFingerprint.superclassName()
// Returns: "zio.test.ZIOSpecAbstract"Indicates that ZIO specs are typically implemented as Scala objects (modules), not classes.
ZioSpecFingerprint.isModule()
// Returns: trueSpecifies that ZIO specs don't require no-argument constructors since they're objects.
ZioSpecFingerprint.requireNoArgConstructor()
// Returns: falseThe JVM implementation provides the full feature set:
final class ZTestFramework extends sbt.testing.Framework {
override val name: String = s"${Console.UNDERLINED}ZIO Test${Console.RESET}"
val fingerprints: Array[sbt.testing.Fingerprint] = Array(ZioSpecFingerprint)
override def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): ZTestRunnerJVM
}JavaScript implementation supports both master and slave runner patterns for distributed testing:
final class ZTestFramework extends sbt.testing.Framework {
override final val name: String = s"${Console.UNDERLINED}ZIO Test${Console.RESET}"
val fingerprints: Array[sbt.testing.Fingerprint] = Array(ZioSpecFingerprint)
override def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): sbt.testing.Runner
override def slaveRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
send: String => Unit
): sbt.testing.Runner
}Similar to JavaScript but with platform-specific optimizations:
final class ZTestFramework extends sbt.testing.Framework {
override def name(): String = s"${Console.UNDERLINED}ZIO Test${Console.RESET}"
override def fingerprints(): Array[sbt.testing.Fingerprint] = Array(ZioSpecFingerprint)
override def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): sbt.testing.Runner
override def slaveRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
send: String => Unit
): sbt.testing.Runner
}// build.sbt
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
libraryDependencies += "dev.zio" %% "zio-test-sbt" % "2.1.19" % TestFor advanced scenarios where you need to programmatically register the framework:
import sbt.testing._
val framework = new zio.test.sbt.ZTestFramework()
val fingerprints = framework.fingerprints
// Verify framework can discover ZIO specs
fingerprints.foreach { fingerprint =>
println(s"Looking for: ${fingerprint match {
case sf: SubclassFingerprint => sf.superclassName()
case af: AnnotatedFingerprint => af.annotationName()
}}")
}