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

cross-platform-execution.mddocs/

Cross-Platform Test Execution

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.

Capabilities

JavaScript Platform Runners

JavaScript platform provides distributed test execution with master/slave coordination for running tests in browser environments or Node.js workers.

ZTestRunnerJS Base Class

/**
 * 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
}

ZMasterTestRunnerJS

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
    ()
  }
}

ZSlaveTestRunnerJS

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 Runners

Scala Native platform provides similar distributed execution capabilities optimized for native binary execution.

ZTestRunnerNative Base Class

/**
 * 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
}

Native Platform Implementations

/**
 * 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 ZTestRunnerNative

Cross-Platform Test Tasks

Both JavaScript and Native platforms use similar task implementations that extend the shared BaseTestTask.

JavaScript Test Task

/**
 * 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
}

Native Test Task

/**
 * 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]
}

Summary Serialization Protocol

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
}

Platform Differences

FeatureJavaScriptScala NativeJVM
Execution ModelAsync with continuationsSync with blockingSync with advanced features
Summary Storagemutable.BufferConcurrentLinkedQueueAtomicReference[Vector]
Distributed SupportMaster/SlaveMaster/SlaveSingle process
Signal HandlingNoNoYes (USR1, INFO, INT)
Runtime SharingDefault runtimeDefault runtimeShared scoped runtime
Resource CleanupBasicBasicAdvanced with shutdown hooks

Configuration Examples

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")