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

native-platform.mddocs/

Native Platform Support

Scala Native test runner optimized for native compilation with efficient memory usage and native-specific execution patterns. Provides cross-platform compatibility for native executables.

Capabilities

ZTestRunnerNative Base Class

Abstract base class for Scala Native test runners that provides common functionality optimized for native compilation and execution.

/**
 * Base Scala Native test runner with master/slave architecture support
 * Optimized for native compilation with efficient memory usage
 */
sealed abstract class ZTestRunnerNative(
  val args: Array[String],
  remoteArgs0: Array[String],
  testClassLoader: ClassLoader,
  runnerType: String
) extends Runner {
  /** Get remote execution arguments */
  def remoteArgs(): Array[String]
  
  /** Abstract method for summary handling strategy */
  def sendSummary: SendSummary
  
  /** Thread-safe queue for collecting test summaries */
  val summaries: ConcurrentLinkedQueue[Summary]
  
  /**
   * Create test tasks from discovered test definitions
   * @param defs Array of SBT task definitions
   * @return Array of executable native test tasks
   */
  def tasks(defs: Array[TaskDef]): Array[Task]
  
  /**
   * Complete test execution and return formatted results
   * Efficiently processes summaries with minimal memory allocation
   * @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 Native)
   */
  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
}

ZMasterTestRunner

Master runner for single-process Scala Native execution, optimized for native executable environments.

/**
 * Master Scala Native test runner for single-process execution
 * Provides efficient local summary collection for native executables
 */
final class ZMasterTestRunner(
  args: Array[String], 
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader
) extends ZTestRunnerNative(args, remoteArgs, testClassLoader, "master") {
  /**
   * Summary sender that collects results locally using thread-safe queue
   * Optimized for native execution with minimal overhead
   */
  override val sendSummary: SendSummary
}

ZSlaveTestRunner

Slave runner for distributed Scala Native execution, used when tests are executed across multiple native processes.

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

ZTestTask (Native)

Scala Native-specific test task implementation with blocking execution optimized for native environments.

/**
 * Scala Native-specific test task with blocking execution
 * Optimized for native compilation and minimal memory usage
 */
sealed 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
) {
  /**
   * Execute test with blocking semantics suitable for native execution
   * Uses Await.result for synchronous execution model
   * @param eventHandler SBT event handler for reporting
   * @param loggers Array of SBT loggers
   * @return Empty array (no sub-tasks created)
   */
  override def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[sbt.testing.Task]
}

ZTestTask Companion Object (Native)

Factory methods for creating Scala Native test tasks.

object ZTestTask {
  /**
   * Create a Scala Native 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 native ZTestTask instance
   */
  def apply(
    taskDef: TaskDef,
    testClassLoader: ClassLoader,
    runnerType: String,
    sendSummary: SendSummary,
    args: TestArgs
  ): ZTestTask
}

Efficient Summary Processing

The native platform uses optimized summary processing for minimal memory allocation:

def done(): String = {
  val log = new StringBuilder
  var summary = summaries.poll()
  var total = 0
  var ignore = 0
  val isEmpty = summary eq null
  
  // Process summaries without creating intermediate collections
  while (summary ne null) {
    total += summary.total
    ignore += summary.ignore
    val details = summary.failureDetails
    if (!details.isBlank) {
      log append colored(details)
      log append '\n'
    }
    summary = summaries.poll()
  }
  
  if (isEmpty || total == ignore)
    s"${Console.YELLOW}No tests were executed${Console.RESET}"
  else
    log.append("Done").result()
}

Blocking Execution Model

Native test tasks use blocking execution for simplicity and efficiency:

override def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[sbt.testing.Task] = {
  var resOutter: CancelableFuture[Unit] = null
  try {
    resOutter = Runtime.default.unsafe.runToFuture {
      ZIO.consoleWith { console =>
        (for {
          summary <- spec.runSpecAsApp(FilteredSpec(spec.spec, args), args, console)
          _ <- sendSummary.provideSomeEnvironment[Any](_.add(summary))
          _ <- ZIO.when(summary.status == Summary.Failure) {
                 ZIO.attempt(eventHandler.handle(ZTestEvent(/* failure event */)))
               }
        } yield ()).provideLayer(
          sharedFilledTestLayer +!+ (Scope.default >>> spec.bootstrap)
        )
      }.mapError {
        case t: Throwable => t
        case other => new RuntimeException(s"Unknown error during tests: $other")
      }
    }
    
    // Block until completion for native execution model
    Await.result(resOutter, SDuration.Inf)
    Array()
  } catch {
    case t: Throwable =>
      if (resOutter != null) resOutter.cancel()
      throw t
  }
}

SummaryProtocol (Native)

The native platform uses the same serialization protocol as JavaScript for inter-process communication:

/**
 * Serialization protocol for test summaries in native environments
 * Identical to JavaScript implementation for consistency
 */
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 for serialization
   * @param token String token to escape
   * @return Escaped string
   */
  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
}

Native Platform Optimizations

Scala Native provides several optimizations:

  • Memory Efficiency: Uses ConcurrentLinkedQueue and StringBuilder for minimal allocations
  • Blocking Execution: Simplifies execution model with Await.result for native environments
  • Native Compilation: Optimized for ahead-of-time compilation to native executables
  • Cross-Platform: Works on Linux, macOS, and Windows native targets
  • Fast Startup: Native executables have faster startup compared to JVM
  • Small Binary Size: Compiled to compact native executables

Error Handling

Native execution includes comprehensive error handling:

// Explicit error mapping for native environments
.mapError {
  case t: Throwable => t
  case other => new RuntimeException(s"Unknown error during tests: $other")
}

// Proper resource cleanup on cancellation
catch {
  case t: Throwable =>
    if (resOutter != null) resOutter.cancel()
    throw t
}

Platform Considerations

The native platform has specific considerations:

  • Reflection Limitations: Uses portable reflection for class loading
  • Threading Model: Compatible with native threading constraints
  • Memory Management: Optimized for native garbage collection
  • IO Operations: Works with native file system and console access
  • Signal Handling: Limited compared to JVM but functional for basic needs

Usage Example

// Native framework usage is identical to other platforms
val framework = new ZTestFramework()
val runner = framework.runner(args, remoteArgs, classLoader)

// Native compilation produces fast-starting executable
// $ scala-native:nativeLink
// $ ./target/scala-native/my-tests

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