or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async.mdfixtures.mdindex.mdmatchers.mdproperty.mdscalactic.mdtest-styles.md
tile.json

matchers.mddocs/

Matchers and Assertions

ScalaTest provides a powerful matcher system that enables readable test code and informative failure messages. The matcher system includes basic assertions, should/must matchers, and specialized matchers for different data types.

Capabilities

Basic Assertions

Core assertion methods available in all test suites.

trait Assertions {
  /**
   * Assert that a condition is true
   */
  def assert(condition: Boolean): Assertion
  def assert(condition: Boolean, clue: Any): Assertion
  
  /**
   * Assume a condition (will cancel the test if false rather than fail)
   */
  def assume(condition: Boolean): Assertion
  def assume(condition: Boolean, clue: Any): Assertion
  
  /**
   * Force test failure with optional message
   */
  def fail(): Nothing
  def fail(message: String): Nothing
  def fail(message: String, cause: Throwable): Nothing
  
  /**
   * Mark test as pending
   */
  def pending: Assertion with PendingStatement
  def pending(message: String): Assertion with PendingStatement
  
  /**
   * Cancel test execution with optional message
   */
  def cancel(): Nothing
  def cancel(message: String): Nothing
  def cancel(message: String, cause: Throwable): Nothing
  
  /**
   * Assert that a code block throws a specific exception
   */
  def intercept[T <: AnyRef](f: => Any)(implicit classTag: ClassTag[T]): T
  
  /**
   * Assert that a code block throws an exception of any type
   */
  def assertThrows[T <: AnyRef](f: => Any)(implicit classTag: ClassTag[T]): Assertion
  
  /**
   * Assert that a code block compiles successfully
   */
  def assertCompiles(code: String): Assertion
  
  /**
   * Assert that a code block does not compile
   */
  def assertDoesNotCompile(code: String): Assertion
  
  /**
   * Assert that a code block produces a type error
   */
  def assertTypeError(code: String): Assertion
  
  /**
   * Add a clue to any assertion for better error messages
   */
  def withClue[T](clue: Any)(fun: => T): T
}

Usage Examples:

// Basic assertions
assert(2 + 2 == 4)
assert(2 + 2 == 4, "Basic math should work")

// Exception testing
val exception = intercept[IllegalArgumentException] {
  throw new IllegalArgumentException("Invalid argument")
}
assert(exception.getMessage == "Invalid argument")

// Pending tests
pending // Mark test as pending

// Compile-time assertions (macros)
assertCompiles("val x: Int = 42")
assertDoesNotCompile("val x: String = 42")
assertTypeError("val x: String = 42")

// Enhanced error messages with clues
withClue("When testing user registration:") {
  user.name should not be empty
  user.email should include ("@")
}

Should Matchers

Expressive matchers using "should" syntax.

trait Matchers extends Assertions {
  /**
   * Equality matcher
   */
  def equal(right: Any): Matcher[Any]
  
  /**
   * Identity matcher (checks object identity, not equality)
   */
  def be(right: Any): Matcher[Any]
  
  /**
   * Greater than matcher
   */
  def be(resultOfGreaterThanComparison: ResultOfGreaterThanComparison[_]): Matcher[Any]
  
  /**
   * Less than matcher  
   */
  def be(resultOfLessThanComparison: ResultOfLessThanComparison[_]): Matcher[Any]
  
  /**
   * Collection/string containment matcher
   */
  def contain(element: Any): Matcher[Any]
  
  /**
   * String containment matchers
   */
  def startWith(right: String): Matcher[String]
  def endWith(right: String): Matcher[String]
  def include(substring: String): Matcher[String]
  
  /**
   * Size/length matchers
   */
  def have(resultOfLengthWordApplication: ResultOfLengthWordApplication): Matcher[Any]
  def have(resultOfSizeWordApplication: ResultOfSizeWordApplication): Matcher[Any]
  
  /**
   * Type checking matchers
   */
  def be(aType: ResultOfATypeInvocation[_]): Matcher[Any]
  def be(anType: ResultOfAnTypeInvocation[_]): Matcher[Any]
  
  /**
   * Pattern matching matcher
   */
  def matchPattern(right: PartialFunction[Any, _]): Matcher[Any]
}

/**
 * Implicit conversion to enable should syntax on any value
 */
implicit class Shouldable[T](leftSideValue: T) {
  def should(rightMatcherX1: Matcher[T]): Assertion
  def should(beWord: BeWord): ResultOfBeWordForAny[T]
  def should(notExist: NotExist.type): Assertion
  def should(exist: Exist.type): Assertion
}

Usage Examples:

import org.scalatest.matchers.should.Matchers

// Equality matchers
result should equal (42)
result should === (42)  // Shorthand for equal
result should be (42)

// Comparison matchers  
result should be > 10
result should be < 100
result should be >= 10
result should be <= 100

// String matchers
message should include ("error")
message should startWith ("Error:")
message should endWith ("failed")
message should fullyMatch regex "\\d+".r

// Collection matchers
list should contain (3)
list should contain oneOf (1, 2, 3)
list should contain allOf (1, 2, 3)
list should have length 3
list should have size 3
list should be (empty)
list should not be empty

// Type matchers
obj should be a [String]
obj should be an [IllegalArgumentException]

// Property matchers  
obj should have (
  Symbol("name") ("John"),
  Symbol("age") (25)
)

Must Matchers

Alternative syntax using "must" instead of "should".

/**
 * Implicit conversion to enable must syntax on any value
 */
implicit class Mustable[T](leftSideValue: T) {
  def must(rightMatcherX1: Matcher[T]): Assertion
  def must(beWord: BeWord): ResultOfBeWordForAny[T]
  def must(notExist: NotExist.type): Assertion
  def must(exist: Exist.type): Assertion
}

Usage Examples:

import org.scalatest.matchers.must.Matchers

result must equal (42)
result must be > 10
message must include ("error")
list must contain (3)
list must have length 3

Custom Matchers

Creating custom matchers for domain-specific testing.

trait Matcher[-T] extends (T => MatchResult) {
  def apply(left: T): MatchResult
  
  /**
   * Compose this matcher with another using logical AND
   */
  def and[U <: T](rightMatcher: Matcher[U]): Matcher[U]
  
  /**
   * Compose this matcher with another using logical OR
   */
  def or[U <: T](rightMatcher: Matcher[U]): Matcher[U]
}

case class MatchResult(
  matches: Boolean,
  rawFailureMessage: String,
  rawNegatedFailureMessage: String,
  rawMidSentenceFailureMessage: String = "",
  rawMidSentenceNegatedFailureMessage: String = ""
)

Usage Examples:

// Custom matcher for even numbers
def beEven = Matcher { (left: Int) =>
  MatchResult(
    left % 2 == 0,
    s"$left was not even",
    s"$left was even"
  )
}

// Usage
42 should beEven
43 should not be even

// Composing matchers
def bePositiveAndEven = be > 0 and beEven

// Custom matcher with parameters
def beWithinTolerance(expected: Double, tolerance: Double) = 
  Matcher { (actual: Double) =>
    val difference = Math.abs(actual - expected)
    MatchResult(
      difference <= tolerance,
      s"$actual was not within $tolerance of $expected",
      s"$actual was within $tolerance of $expected"
    )
  }

// Usage  
3.14159 should beWithinTolerance(3.14, 0.01)

Inspectors

Matchers for collections that apply assertions to all or some elements.

trait Inspectors {
  /**
   * Assert that all elements satisfy the condition
   */
  def forAll[E](xs: Iterable[E])(fun: E => Unit): Unit
  
  /**
   * Assert that at least one element satisfies the condition
   */
  def forAtLeast(min: Int, xs: Iterable[_])(fun: Any => Unit): Unit
  
  /**
   * Assert that at most n elements satisfy the condition
   */
  def forAtMost(max: Int, xs: Iterable[_])(fun: Any => Unit): Unit
  
  /**
   * Assert that exactly n elements satisfy the condition
   */
  def forExactly(succeededCount: Int, xs: Iterable[_])(fun: Any => Unit): Unit
  
  /**
   * Assert that between min and max elements satisfy the condition
   */
  def forBetween(from: Int, upTo: Int, xs: Iterable[_])(fun: Any => Unit): Unit
  
  /**
   * Assert that every element satisfies the condition (alias for forAll)
   */
  def forEvery[E](xs: Iterable[E])(fun: E => Unit): Unit
}

Usage Examples:

import org.scalatest.Inspectors

val numbers = List(1, 2, 3, 4, 5)

// All elements should be positive
forAll(numbers) { num =>
  num should be > 0
}

// At least 3 elements should be even
forAtLeast(2, numbers) { num =>
  num % 2 should equal (0)
}

// Exactly one element should equal 3
forExactly(1, numbers) { num =>  
  num should equal (3)
}

Matcher Types

/**
 * Base matcher trait
 */
trait Matcher[-T] extends (T => MatchResult)

/**
 * Helper words and phrases for building matcher expressions
 */
trait BeWord
trait HaveWord  
trait ContainWord
trait ExistWord
trait NotExist

/**
 * Result types for matcher expressions
 */
case class ResultOfBeWordForAny[T](left: T, shouldBeTrue: Boolean)
case class ResultOfLengthWordApplication(expectedLength: Long)
case class ResultOfSizeWordApplication(expectedSize: Long)
case class ResultOfGreaterThanComparison[T](right: T)
case class ResultOfLessThanComparison[T](right: T)

/**
 * Type checking helpers
 */
case class ResultOfATypeInvocation[T](clazz: Class[T])
case class ResultOfAnTypeInvocation[T](clazz: Class[T])