or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

assertions.mdconfiguration.mdexceptions.mdfixtures.mdindex.mdtest-suites.mdtransforms.md
tile.json

configuration.mddocs/

Configuration

Test configuration classes and metadata types for organizing and controlling test execution. This includes test options, tags for categorizing tests, and source location tracking for error reporting.

Capabilities

TestOptions - Test Configuration

Configuration class for customizing individual test behavior including naming, tagging, and execution control.

/**
 * Configuration options for individual tests
 * @param name The test name
 * @param tags Set of tags applied to the test
 * @param location Source code location of the test
 */
final class TestOptions(val name: String, val tags: Set[Tag], val location: Location) extends Serializable {
  
  /** Create a new TestOptions with a different name */
  def withName(newName: String): TestOptions
  
  /** Create a new TestOptions with different tags */
  def withTags(newTags: Set[Tag]): TestOptions
  
  /** Create a new TestOptions with a different location */
  def withLocation(newLocation: Location): TestOptions
  
  /** Add a single tag to this test */
  def tag(t: Tag): TestOptions
  
  // Convenience methods for common tags
  /** Mark this test as expected to fail */
  def fail: TestOptions
  
  /** Mark this test as potentially flaky */
  def flaky: TestOptions
  
  /** Skip this test during execution */
  def ignore: TestOptions
  
  /** Mark this test as pending implementation */
  def pending: TestOptions
  
  /** Mark this test as pending with a comment */
  def pending(comment: String): TestOptions
  
  /** Run only this test (skip all others) */
  def only: TestOptions
}

/**
 * Companion object with factory methods
 */
object TestOptions extends TestOptionsConversions {
  def apply(name: String)(implicit loc: Location): TestOptions
}

/**
 * Implicit conversions for convenience
 */
trait TestOptionsConversions {
  /** Convert a string to TestOptions with current location */
  implicit def testOptionsFromString(name: String)(implicit loc: Location): TestOptions
}

Usage Examples:

class ConfigurationExamples extends FunSuite {
  test("basic test") {
    assert(true)
  }
  
  test("slow integration test".tag(Slow)) {
    // This test is marked as slow
    performIntegrationTest()
  }
  
  test("flaky network test".flaky) {
    // This test may fail intermittently
    callExternalAPI()
  }
  
  test("unimplemented feature".pending) {
    // This test is not yet implemented
  }
  
  test("work in progress".pending("waiting for API changes")) {
    // Pending with a specific reason
  }
  
  test("debug this specific test".only) {
    // Only this test will run when debugging
    assert(complexCondition())
  }
  
  // Combining multiple tags
  test(TestOptions("comprehensive test")
    .tag(Slow)
    .tag(new Tag("integration"))) {
    performComprehensiveTest()
  }
}

Test - Test Case Metadata

Metadata class representing a complete test case with all its configuration and execution details.

/**
 * Complete test case with name, body, tags, and location
 * @param name The test name
 * @param body Function that executes the test and returns a Future
 * @param tags Set of tags applied to this test
 * @param location Source code location where test is defined
 */
final class Test(val name: String, val body: () => Future[Any], val tags: Set[Tag], val location: Location) extends Serializable {
  
  /** Create a new test with a different name */
  def withName(newName: String): Test
  
  /** Create a new test with a different body */
  def withBody(newBody: () => Future[Any]): Test
  
  /** Create a new test with a transformed body */
  def withBodyMap(newBody: Future[Any] => Future[Any]): Test
  
  /** Create a new test with different tags */
  def withTags(newTags: Set[Tag]): Test
  
  /** Add a single tag to this test */
  def tag(newTag: Tag): Test
  
  /** Create a new test with a different location */
  def withLocation(newLocation: Location): Test
  
  /** Get annotations for this test (includes tags and location) */
  def annotations: Array[Annotation]
}

Tag - Test Categories

Tags for categorizing and controlling test execution behavior.

/**
 * Base tag class for categorizing tests
 * @param value The tag identifier string
 */
class Tag(val value: String) extends munit.internal.junitinterface.Tag with Annotation with Serializable

Built-in Tags:

// Pre-defined tags available in the munit package object
val Ignore = new Tag("Ignore")     // Skip this test
val Only = new Tag("Only")         // Run only this test  
val Flaky = new Tag("Flaky")       // Test may fail intermittently
val Fail = new Tag("Fail")         // Test is expected to fail
val Pending: Tag with PendingTag = new Tag("Pending") with PendingTag  // Test is pending implementation
val Slow = new Tag("Slow")         // Test is slow running

/**
 * Pending tag with custom comment
 * @param value The comment explaining why test is pending
 */
case class PendingComment(override val value: String) extends Tag(value) with PendingCommentTag

Usage Examples:

class TagExamples extends FunSuite {
  test("regular test") {
    assert(true)
  }
  
  test("skip this test".tag(Ignore)) {
    // This test will be skipped
    fail("Should not run")
  }
  
  test("database test".tag(Slow).tag(new Tag("database"))) {
    // Multiple tags can be applied
    connectToDatabase()
  }
  
  // Custom tags
  val Integration = new Tag("Integration")  
  val External = new Tag("External")
  
  test("API integration".tag(Integration).tag(External)) {
    callExternalAPI()
  }
  
  // Environment-specific tags
  test("linux only test".tag(new Tag("linux"))) {
    assume(System.getProperty("os.name").toLowerCase.contains("linux"))
    // Test linux-specific functionality
  }
}

Location - Source Code Location

Source code location tracking for precise error reporting and IDE integration.

/**
 * Source code location information
 * @param path The file path where the test is defined
 * @param line The line number in the file
 */
final class Location(val path: String, val line: Int) extends Annotation with Serializable {
  
  /** Extract just the filename from the full path */
  def filename: String
  
  /** Format location as "path:line" */
  override def toString: String
}

/**
 * Companion object with utility methods
 */
object Location extends MacroCompat.LocationMacro {
  /** Empty location placeholder for tests created programmatically */
  def empty: Location
}

Usage Examples:

class LocationExamples extends FunSuite {
  test("location is automatically captured") {
    // Location is captured via macro at compile time
    assert(true)
  }
  
  // Manual test creation with explicit location
  val manualTest = new Test(
    "manual test",
    () => Future.successful(assert(true)),
    Set.empty,
    new Location("MyTest.scala", 42)
  )
}

Tag-Based Test Execution

Environment Variables

MUnit respects several environment variables for controlling test execution:

  • MUNIT_FLAKY_OK: Set to allow flaky tests to pass even if they fail
  • CI: Detected automatically to adjust behavior in continuous integration

Test Filtering

Tags can be used with build tools and IDEs to filter which tests run:

// Run only slow tests
sbt 'testOnly -- --include-tags=Slow'

// Exclude flaky tests  
sbt 'testOnly -- --exclude-tags=Flaky'

// Run tests with multiple tags
sbt 'testOnly -- --include-tags=Integration,Database'

Custom Tag Patterns

Create domain-specific tags for your project:

object TestTags {
  val Unit = new Tag("Unit")
  val Integration = new Tag("Integration") 
  val Performance = new Tag("Performance")
  val Security = new Tag("Security")
  val UI = new Tag("UI")
  val API = new Tag("API")
}

class ServiceTests extends FunSuite {
  import TestTags._
  
  test("unit test".tag(Unit)) {
    // Fast unit test
  }
  
  test("integration test".tag(Integration).tag(Slow)) {
    // Slower integration test
  }
  
  test("performance benchmark".tag(Performance).tag(Slow)) {
    // Performance testing
  }
}

Compare - Type-Safe Comparisons

Type-class that enables type-safe comparisons in MUnit assertions with custom failure handling.

/**
 * Type-class for comparing values in MUnit assertions
 * Enables type-safe comparisons between related types
 */
trait Compare[A, B] {
  
  /** Check if two values are equal according to comparison rules */
  def isEqual(obtained: A, expected: B): Boolean
  
  /** Handle comparison failures with custom error messages and diff output */
  def failEqualsComparison(obtained: A, expected: B, title: Any, assertions: Assertions)(implicit loc: Location, options: DiffOptions): Nothing
}

/**
 * Companion object providing default comparison implementations
 */
object Compare extends ComparePriority1 {
  /** Default comparison using == for any two types */
  def defaultCompare[A, B]: Compare[A, B]
}

/**
 * Implicit priority for subtype comparisons
 */
trait ComparePriority1 extends ComparePriority2 {
  /** Allow comparison when A is a subtype of B */
  implicit def compareSubtypeWithSupertype[A, B](implicit ev: A <:< B): Compare[A, B]
}

/**
 * Implicit priority for supertype comparisons  
 */
trait ComparePriority2 {
  /** Allow comparison when B is a subtype of A */
  implicit def compareSupertypeWithSubtype[A, B](implicit ev: A <:< B): Compare[B, A]
}

Usage Examples:

// Custom comparison for domain objects
implicit val userCompare: Compare[User, User] = new Compare[User, User] {
  def isEqual(obtained: User, expected: User): Boolean = 
    obtained.id == expected.id && obtained.email == expected.email
    
  def failEqualsComparison(obtained: User, expected: User, title: Any, assertions: Assertions)(implicit loc: Location, options: DiffOptions): Nothing =
    assertions.failComparison(s"Users not equal: $title", obtained, expected)
}

class UserTests extends FunSuite {
  test("user equality") {
    val user1 = User(1, "alice@example.com", "Alice")
    val user2 = User(1, "alice@example.com", "Alice Smith") // Different name
    assertEquals(user1, user2) // Uses custom comparison (ignores name)
  }
}

Printable - Custom Pretty-Printing

Interface for customizing how values are displayed in test failure messages.

/**
 * Interface for objects that can customize their printed representation
 */
trait Printable {
  /** Append custom representation to a StringBuilder */
  def print(out: StringBuilder, indent: Int): Unit
}

Usage Examples:

case class ComplexData(values: Map[String, Any]) extends Printable {
  def print(out: StringBuilder, indent: Int): Unit = {
    out.append("ComplexData(\n")
    values.foreach { case (key, value) =>
      out.append("  " * (indent + 1))
      out.append(s"$key = $value\n")
    }
    out.append("  " * indent)
    out.append(")")
  }
}

class PrintableTests extends FunSuite {
  test("complex data comparison") {
    val data1 = ComplexData(Map("x" -> 1, "y" -> 2))
    val data2 = ComplexData(Map("x" -> 1, "y" -> 3))
    
    // Custom printing will be used in failure message
    assertEquals(data1, data2)
  }
}

MUnitRunner - Test Framework Integration

JUnit runner that enables MUnit integration with IDEs and build tools.

/**
 * JUnit runner for MUnit test suites
 * Automatically applied to Suite classes via @RunWith annotation
 */
class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) extends Runner

/**
 * Companion object with runner utilities
 */
object MUnitRunner {
  /** Create a runner for a suite class */
  def apply(cls: Class[_ <: Suite]): MUnitRunner
}

Usage:

// Automatically applied to all Suite subclasses
@RunWith(classOf[MUnitRunner])
abstract class Suite extends PlatformSuite {
  // Suite implementation
}