CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scala-js--scalajs-test-interface

Scala.js version of the sbt testing interface that provides a standardized API for test frameworks to integrate with SBT and run tests in a Scala.js (JavaScript) environment

Pending
Overview
Eval results
Files

framework.mddocs/

Framework Implementation

Framework implementation interface for creating test frameworks that integrate with SBT and support distributed testing in Scala.js environments.

Capabilities

Framework Trait

Main interface that test frameworks must implement to integrate with the SBT testing infrastructure.

/**
 * Interface implemented by test frameworks.
 * Must be annotated with @EnableReflectiveInstantiation for Scala.js compatibility.
 */
trait Framework {
  /** A human-friendly name of the test framework that this object represents. */
  def name(): String
  
  /** An array of Fingerprints that specify how to identify test classes during discovery. */
  def fingerprints(): Array[Fingerprint]
  
  /** 
   * Initiates a run.
   * @param args the test-framework-specific arguments for the new run
   * @param remoteArgs the test-framework-specific remote arguments for the run in a forked JVM
   * @param testClassLoader a class loader to use when loading test classes during the run
   * @return a Runner representing the newly started run
   * @throws IllegalStateException if unable to initiate run due to concurrent execution
   */
  def runner(args: Array[String], remoteArgs: Array[String],
            testClassLoader: ClassLoader): Runner
  
  /**
   * Scala.js specific: Creates a worker runner for a given run.
   * The worker may send a message to the controller runner by calling `send`.
   * Note: This method is called `slaveRunner` rather than `workerRunner` for historical reasons.
   * @param args the test-framework-specific arguments
   * @param remoteArgs the test-framework-specific remote arguments
   * @param testClassLoader class loader for test classes
   * @param send function to send messages to the controller runner
   * @return a Runner for worker execution
   */
  def slaveRunner(args: Array[String], remoteArgs: Array[String],
                 testClassLoader: ClassLoader, send: String => Unit): Runner
}

Usage Examples:

import sbt.testing._
import scala.scalajs.reflect.annotation.EnableReflectiveInstantiation

@EnableReflectiveInstantiation
class MyTestFramework extends Framework {
  def name(): String = "MyFramework"
  
  def fingerprints(): Array[Fingerprint] = Array(
    // Discover classes extending MyTestSuite
    new SubclassFingerprint {
      def isModule() = false
      def superclassName() = "com.example.MyTestSuite"
      def requireNoArgConstructor() = true
    },
    // Discover objects with @Test annotation
    new AnnotatedFingerprint {
      def isModule() = true
      def annotationName() = "com.example.Test"
    }
  )
  
  def runner(args: Array[String], remoteArgs: Array[String], 
            testClassLoader: ClassLoader): Runner = {
    new MyTestRunner(args, remoteArgs, testClassLoader, isWorker = false)
  }
  
  def slaveRunner(args: Array[String], remoteArgs: Array[String],
                 testClassLoader: ClassLoader, send: String => Unit): Runner = {
    new MyWorkerRunner(args, remoteArgs, testClassLoader, send)
  }
}

// Controller runner implementation
class MyTestRunner(
  val args: Array[String],
  remoteArgs: Array[String], 
  testClassLoader: ClassLoader,
  isWorker: Boolean
) extends Runner {
  // ... implementation
}

// Worker runner with message passing
class MyWorkerRunner(
  val args: Array[String],
  remoteArgs: Array[String],
  testClassLoader: ClassLoader,
  send: String => Unit
) extends Runner {
  
  def receiveMessage(msg: String): Option[String] = {
    msg match {
      case "status" => Some("worker-ready")
      case "shutdown" => 
        cleanup()
        None
      case _ => None
    }
  }
  
  // ... other implementations
}

Reflective Instantiation

Scala.js-specific annotation required for framework discovery and instantiation.

/**
 * Annotation from scala.scalajs.reflect.annotation package
 * Must be applied to Framework implementations for Scala.js compatibility
 */
@EnableReflectiveInstantiation

Usage:

import scala.scalajs.reflect.annotation.EnableReflectiveInstantiation

@EnableReflectiveInstantiation
class MyFramework extends Framework {
  // Implementation
}

Error Handling

IllegalStateException

Thrown by runner() method when framework cannot initiate concurrent runs:

def runner(args: Array[String], remoteArgs: Array[String],
          testClassLoader: ClassLoader): Runner = {
  if (isRunning) {
    throw new IllegalStateException(
      "Cannot initiate new run while previous run is active"
    )
  }
  // ... create runner
}

Framework Lifecycle

  1. Discovery: SBT discovers framework classes through service loading
  2. Instantiation: Framework instance created using reflective instantiation
  3. Fingerprint Registration: fingerprints() called to get test discovery patterns
  4. Runner Creation: runner() or slaveRunner() called to create test runners
  5. Test Execution: Runners execute tests and report results
  6. Cleanup: Framework resources cleaned up after test completion

Install with Tessl CLI

npx tessl i tessl/maven-org-scala-js--scalajs-test-interface

docs

discovery.md

events.md

execution.md

framework.md

index.md

logging.md

tile.json