CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-dev-zio--zio-test-sbt-3

ZIO Test SBT Framework integration that provides test interface implementation for running ZIO-based tests within SBT build environments

Pending
Overview
Eval results
Files

js-platform.mddocs/

JavaScript Platform Support

Lightweight JavaScript test runner with master/slave architecture for distributed test execution and inter-process communication through serialized summaries. Optimized for Scala.js compilation and browser/Node.js environments.

Capabilities

ZTestRunnerJS Base Class

Abstract base class for JavaScript test runners that provides common functionality for both master and slave execution modes.

/**
 * Base JavaScript test runner with master/slave architecture support
 * Provides lightweight execution optimized for JavaScript environments
 */
sealed abstract class ZTestRunnerJS(
  val args: Array[String],
  val remoteArgs: Array[String],
  testClassLoader: ClassLoader,
  runnerType: String
) extends Runner {
  /** Abstract method for summary handling strategy */
  def sendSummary: SendSummary
  
  /** Mutable buffer for collecting test summaries */
  val summaries: mutable.Buffer[Summary]
  
  /**
   * Create test tasks from discovered test definitions
   * @param defs Array of SBT task definitions
   * @return Array of executable JavaScript test tasks
   */
  def tasks(defs: Array[TaskDef]): Array[Task]
  
  /**
   * Complete test execution and return formatted results
   * @return Formatted test results or "No tests executed" message
   */
  def done(): String
  
  /**
   * Receive serialized summaries from distributed execution
   * @param summary Serialized summary string from SummaryProtocol
   * @return Optional response message (always None for JS)
   */
  override def receiveMessage(summary: String): Option[String]
  
  /**
   * Serialize task for distributed execution
   * @param task Task to serialize
   * @param serializer SBT-provided serialization function
   * @return Serialized task string
   */
  override def serializeTask(task: Task, serializer: TaskDef => String): String
  
  /**
   * Deserialize task from distributed execution
   * @param task Serialized task string
   * @param deserializer SBT-provided deserialization function  
   * @return Reconstructed test task
   */
  override def deserializeTask(task: String, deserializer: String => TaskDef): Task
}

ZMasterTestRunnerJS

Master runner for single-process JavaScript execution, typically used when running tests in a single JavaScript context.

/**
 * Master JavaScript test runner for single-process execution
 * Collects summaries directly without inter-process communication
 */
final class ZMasterTestRunnerJS(
  args: Array[String], 
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "master") {
  /**
   * Summary sender that collects results locally
   * Used when all tests run in the same JavaScript context
   */
  override val sendSummary: SendSummary
}

ZSlaveTestRunnerJS

Slave runner for distributed JavaScript execution, used when tests are executed across multiple JavaScript contexts or processes.

/**
 * Slave JavaScript test runner for distributed execution
 * Sends summaries to master process via serialization protocol
 */
final class ZSlaveTestRunnerJS(
  args: Array[String],
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader,
  val sendSummary: SendSummary
) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "slave")

ZTestTask (JavaScript)

JavaScript-specific test task implementation with asynchronous execution support.

/**
 * JavaScript-specific test task with async execution
 * Optimized for JavaScript event loop and browser/Node.js environments  
 */
sealed 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
) {
  /**
   * Execute test with async continuation support
   * Required for JavaScript's asynchronous execution model
   * @param eventHandler SBT event handler for reporting
   * @param loggers Array of SBT loggers
   * @param continuation Continuation function called when execution completes
   */
  def execute(eventHandler: EventHandler, loggers: Array[Logger], continuation: Array[Task] => Unit): Unit
}

ZTestTask Companion Object (JavaScript)

Factory methods for creating JavaScript test tasks.

object ZTestTask {
  /**
   * Create a JavaScript test task instance
   * @param taskDef SBT task definition
   * @param testClassLoader ClassLoader for loading test classes
   * @param runnerType Runner type identifier ("master" or "slave")
   * @param sendSummary Summary collection effect
   * @param args Parsed test arguments
   * @return Configured JavaScript ZTestTask instance
   */
  def apply(
    taskDef: TaskDef,
    testClassLoader: ClassLoader,
    runnerType: String,
    sendSummary: SendSummary,
    args: TestArgs
  ): ZTestTask
}

SummaryProtocol

Serialization protocol for inter-process communication in distributed JavaScript execution.

/**
 * Serialization protocol for test summaries in JavaScript environments
 * Enables communication between master and slave processes
 */
object SummaryProtocol {
  /**
   * Serialize test summary to string for transmission
   * @param summary Test execution summary to serialize
   * @return Tab-separated string representation
   */
  def serialize(summary: Summary): String
  
  /**
   * Deserialize string back to test summary
   * @param s Serialized summary string
   * @return Optional Summary if deserialization succeeds
   */
  def deserialize(s: String): Option[Summary]
  
  /**
   * Escape tab characters in tokens for serialization
   * @param token String token to escape
   * @return Escaped string safe for tab-separated format
   */
  def escape(token: String): String
  
  /**
   * Unescape tab characters from serialized tokens
   * @param token Escaped string token
   * @return Unescaped original string
   */
  def unescape(token: String): String
}

Asynchronous Execution

JavaScript test tasks use asynchronous execution with continuations:

def execute(eventHandler: EventHandler, loggers: Array[Logger], continuation: Array[Task] => Unit): Unit = {
  // Fork execution on default runtime
  val fiber = Runtime.default.unsafe.fork {
    val logic = ZIO.consoleWith { console =>
      (for {
        summary <- spec.runSpecAsApp(FilteredSpec(spec.spec, args), args, console)
        _ <- sendSummary.provide(ZLayer.succeed(summary))
        _ <- ZIO.when(summary.status == Summary.Failure) {
               ZIO.attempt(eventHandler.handle(ZTestEvent(/* failure event */)))
             }
      } yield ()).provideLayer(sharedFilledTestLayer +!+ (Scope.default >>> spec.bootstrap))
    }
    logic
  }
  
  // Add observer for completion handling
  fiber.unsafe.addObserver { exit =>
    exit match {
      case Exit.Failure(cause) => Console.err.println(s"$runnerType failed. $cause")
      case _ =>
    }
    continuation(Array())
  }
}

Master/Slave Architecture

Master Process Flow:

  1. Receives test definitions from SBT
  2. Creates test tasks for local execution
  3. Collects summaries directly in local buffer
  4. Aggregates results and reports to SBT

Slave Process Flow:

  1. Receives serialized tasks from master
  2. Executes tests in isolated JavaScript context
  3. Serializes summaries using SummaryProtocol
  4. Sends results back to master via send function

Platform Optimizations

JavaScript platform provides several optimizations:

  • Lightweight Runtime: Uses default ZIO runtime without heavy JVM features
  • Async Execution: Leverages JavaScript event loop for non-blocking execution
  • Serialization Protocol: Efficient string-based communication for distributed execution
  • Browser Compatibility: Works in both Node.js and browser environments
  • Small Bundle Size: Minimal overhead for Scala.js compilation

Usage Example

// Framework automatically creates appropriate runner type
val framework = new ZTestFramework()

// For single-process execution
val masterRunner = framework.runner(args, remoteArgs, classLoader)

// For distributed execution  
val slaveRunner = framework.slaveRunner(args, remoteArgs, classLoader, summaryCallback)

// SBT handles task serialization/deserialization automatically
val serializedTask = masterRunner.serializeTask(task, serializer)
val deserializedTask = slaveRunner.deserializeTask(serializedTask, deserializer)

Install with Tessl CLI

npx tessl i tessl/maven-dev-zio--zio-test-sbt-3

docs

event-handling.md

framework-integration.md

index.md

js-platform.md

jvm-platform.md

native-platform.md

test-discovery.md

tile.json