JavaScript and Scala Native test runners with distributed execution support for running tests across multiple processes or workers. These platforms support master/slave execution patterns for parallel test execution and memory isolation.
JavaScript platform provides distributed test execution with master/slave coordination for running tests in browser environments or Node.js workers.
/**
* Abstract base class for JavaScript test runners
* Extends sbt.testing.Runner
*/
abstract class ZTestRunnerJS(
val args: Array[String],
val remoteArgs: Array[String],
testClassLoader: ClassLoader,
runnerType: String
) extends Runner {
/** Abstract summary transmission function */
def sendSummary: SendSummary
/** Mutable buffer for collecting test summaries */
val summaries: mutable.Buffer[Summary]
/** Creates test tasks from task definitions */
def tasks(defs: Array[TaskDef]): Array[Task]
/** Returns final aggregated test results */
def done(): String
/** Handles summary messages in distributed execution */
def receiveMessage(summary: String): Option[String]
/** Serializes tasks for distributed execution */
def serializeTask(task: Task, serializer: TaskDef => String): String
/** Deserializes tasks from distributed execution */
def deserializeTask(task: String, deserializer: String => TaskDef): Task
}Master runner for JavaScript platform that coordinates local test execution.
/**
* Master runner for JavaScript platform
* Handles local test execution and summary collection
*/
class ZMasterTestRunnerJS(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "master") {
/** Local summary collection implementation */
val sendSummary: SendSummary = SendSummary.fromSend { summary =>
summaries += summary
()
}
}Slave runner for distributed JavaScript test execution that sends results back to the master.
/**
* Slave runner for distributed JavaScript test execution
* Sends results back to master process
*/
class ZSlaveTestRunnerJS(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
val sendSummary: SendSummary
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "slave")Usage Example:
// In a web worker or separate Node.js process
// Slave runner sends serialized summaries to master
const slaveRunner = new ZSlaveTestRunnerJS(args, remoteArgs, classLoader, sendSummary);Scala Native platform provides similar distributed execution capabilities optimized for native binary execution.
/**
* Abstract base class for Scala Native test runners
* Extends sbt.testing.Runner
*/
abstract class ZTestRunnerNative(
val args: Array[String],
remoteArgs0: Array[String],
testClassLoader: ClassLoader,
runnerType: String
) extends Runner {
/** Remote arguments accessor */
def remoteArgs(): Array[String] = remoteArgs0
/** Abstract summary transmission function */
def sendSummary: SendSummary
/** Thread-safe queue for collecting test summaries */
val summaries: ConcurrentLinkedQueue[Summary]
/** Creates test tasks from task definitions */
def tasks(defs: Array[TaskDef]): Array[Task]
/** Returns final aggregated test results with optimized string building */
def done(): String
/** Handles summary messages in distributed execution */
def receiveMessage(summary: String): Option[String]
/** Serializes/deserializes tasks for distributed execution */
def serializeTask(task: Task, serializer: TaskDef => String): String
def deserializeTask(task: String, deserializer: String => TaskDef): Task
}/**
* Master runner for Scala Native platform
*/
class ZMasterTestRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader
) extends ZTestRunnerNative {
/** Local summary collection with thread-safe queue */
val sendSummary: SendSummary = SendSummary.fromSend { summary =>
summaries.offer(summary)
()
}
}
/**
* Slave runner for distributed Scala Native test execution
*/
class ZSlaveTestRunner(
args: Array[String],
remoteArgs: Array[String],
testClassLoader: ClassLoader,
val sendSummary: SendSummary
) extends ZTestRunnerNativeBoth JavaScript and Native platforms use similar task implementations that extend the shared BaseTestTask.
/**
* JavaScript platform test task
* Executes tests asynchronously with continuation-based completion
*/
class ZTestTask(
taskDef: TaskDef,
testClassLoader: ClassLoader,
runnerType: String,
sendSummary: SendSummary,
testArgs: TestArgs,
spec: ZIOSpecAbstract
) extends BaseTestTask(
taskDef, testClassLoader, sendSummary, testArgs, spec,
Runtime.default, zio.Console.ConsoleLive
) {
/** Asynchronous execution with fiber-based completion handling */
def execute(
eventHandler: EventHandler,
loggers: Array[Logger],
continuation: Array[Task] => Unit
): Unit
}/**
* Scala Native platform test task
* Executes tests synchronously with blocking completion
*/
class ZTestTask(
taskDef: TaskDef,
testClassLoader: ClassLoader,
runnerType: String,
sendSummary: SendSummary,
testArgs: TestArgs,
spec: ZIOSpecAbstract
) extends BaseTestTask(
taskDef, testClassLoader, sendSummary, testArgs, spec,
zio.Runtime.default, zio.Console.ConsoleLive
) {
/** Synchronous execution with blocking result waiting */
override def execute(
eventHandler: EventHandler,
loggers: Array[Logger]
): Array[sbt.testing.Task]
}Cross-platform execution requires serializing test summaries for transmission between processes.
/**
* Serialization protocol for test summaries
* Used in JavaScript and Native distributed execution
*/
object SummaryProtocol {
/** Converts Summary to tab-separated string representation */
def serialize(summary: Summary): String
/** Parses string back to Summary object */
def deserialize(s: String): Option[Summary]
/** Escapes tab characters in string tokens for serialization */
private def escape(token: String): String
/** Unescapes tab characters in deserialized tokens */
private def unescape(token: String): String
}Usage Example:
// Master process receiving results from slave
override def receiveMessage(summary: String): Option[String] = {
SummaryProtocol.deserialize(summary).foreach { s =>
summaries += s // JavaScript: mutable.Buffer
// or
summaries.offer(s) // Native: ConcurrentLinkedQueue
}
None
}| Feature | JavaScript | Scala Native | JVM |
|---|---|---|---|
| Execution Model | Async with continuations | Sync with blocking | Sync with advanced features |
| Summary Storage | mutable.Buffer | ConcurrentLinkedQueue | AtomicReference[Vector] |
| Distributed Support | Master/Slave | Master/Slave | Single process |
| Signal Handling | No | No | Yes (USR1, INFO, INT) |
| Runtime Sharing | Default runtime | Default runtime | Shared scoped runtime |
| Resource Cleanup | Basic | Basic | Advanced with shutdown hooks |
JavaScript (Node.js):
// build.sbt
scalaJSUseMainModuleInitializer := true
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")Scala Native:
// build.sbt
nativeConfig ~= { _.withMode(Mode.debug) }
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")