Comprehensive assertion library with combinable assertions, smart error messages, and detailed failure reporting.
Simple assertion functions for common testing scenarios.
/**
* Assert that all boolean expressions are true
* @param exprs boolean expressions to evaluate
* @return test result indicating success or failure
*/
def assertTrue(exprs: Boolean*): TestResult
/**
* Assert a value against an assertion
* @param expr value to test
* @param assertion assertion to apply
* @return test result
*/
def assert[A](expr: => A)(assertion: Assertion[A]): TestResult
/**
* Assert an effectful computation against an assertion
* @param effect ZIO effect producing value to test
* @param assertion assertion to apply to the result
* @return effectful test result
*/
def assertZIO[R, E, A](effect: ZIO[R, E, A])(assertion: Assertion[A]): ZIO[R, E, TestResult]
/**
* Assert that a test completes successfully
*/
def assertCompletes: TestResult
/**
* Assert that a test never completes (useful for timeout testing)
* @param message descriptive failure message
*/
def assertNever(message: String): TestResultUsage Examples:
import zio.test._
import zio.test.Assertion._
// Basic assertions
assertTrue(2 + 2 == 4)
assertTrue(List(1, 2, 3).nonEmpty, List(1, 2, 3).size == 3)
// Value assertions
assert(List(1, 2, 3))(hasSize(equalTo(3)))
assert("hello world")(startsWith("hello"))
assert(42)(isGreaterThan(0) && isLessThan(100))
// Effectful assertions
assertZIO(ZIO.succeed(List(1, 2, 3)))(contains(2))
assertZIO(database.getUser(123))(hasField("name", equalTo("Alice")))Core trait for building composable assertions.
/**
* An assertion that can be applied to values of type A
*/
trait Assertion[-A] {
/**
* Apply the assertion to a value
* @param value value to test
* @return test result
*/
def apply(value: A): TestResult
/**
* Combine with another assertion using logical AND
* @param that other assertion
* @return combined assertion
*/
def &&(that: Assertion[A]): Assertion[A]
/**
* Combine with another assertion using logical OR
* @param that other assertion
* @return combined assertion
*/
def ||(that: Assertion[A]): Assertion[A]
/**
* Negate this assertion
* @return negated assertion
*/
def unary_! : Assertion[A]
/**
* Add a custom label to this assertion
* @param message descriptive label
* @return labeled assertion
*/
def ??(message: String): Assertion[A]
}Fundamental assertion functions for common data types and operations.
// Equality and comparison
def equalTo[A](expected: A): Assertion[A]
def not[A](assertion: Assertion[A]): Assertion[A]
def anything: Assertion[Any]
def nothing: Assertion[Any]
// Boolean assertions
val isTrue: Assertion[Boolean]
val isFalse: Assertion[Boolean]
// Null/Option assertions
val isNull: Assertion[Any]
val isNonNull: Assertion[Any]
def isSome[A](assertion: Assertion[A]): Assertion[Option[A]]
val isNone: Assertion[Option[A]]
// Numeric comparisons
def isGreaterThan[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
def isGreaterThanEqualTo[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
def isLessThan[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
def isLessThanEqualTo[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
def isWithin[A](reference: A, tolerance: A)(implicit num: Numeric[A]): Assertion[A]
// String assertions
def startsWith(prefix: String): Assertion[String]
def endsWith(suffix: String): Assertion[String]
def containsString(substring: String): Assertion[String]
def matchesRegex(regex: Regex): Assertion[String]
def hasLength(assertion: Assertion[Int]): Assertion[String]
val isEmptyString: Assertion[String]
val isNonEmptyString: Assertion[String]Usage Examples:
import zio.test.Assertion._
// Equality and comparison
assert(42)(equalTo(42))
assert("test")(not(equalTo("other")))
// Boolean
assert(true)(isTrue)
assert(false)(isFalse)
// Numeric
assert(10)(isGreaterThan(5))
assert(3.14)(isWithin(3.0, 0.2))
// String
assert("hello world")(startsWith("hello"))
assert("hello world")(endsWith("world"))
assert("hello world")(containsString("lo wo"))
assert("abc123")(matchesRegex("\\w+\\d+".r))Assertions for testing collections, iterables, and sequences.
// Size and emptiness
def hasSize[A](assertion: Assertion[Int]): Assertion[Iterable[A]]
val isEmpty: Assertion[Iterable[Any]]
val isNonEmpty: Assertion[Iterable[Any]]
// Element membership
def contains[A](element: A): Assertion[Iterable[A]]
def containsAll[A](elements: A*): Assertion[Iterable[A]]
def exists[A](assertion: Assertion[A]): Assertion[Iterable[A]]
def forall[A](assertion: Assertion[A]): Assertion[Iterable[A]]
// Sequence operations
def startsWith[A](prefix: Seq[A]): Assertion[Seq[A]]
def endsWith[A](suffix: Seq[A]): Assertion[Seq[A]]
def hasAt[A](index: Int)(assertion: Assertion[A]): Assertion[Seq[A]]
def hasFirst[A](assertion: Assertion[A]): Assertion[Seq[A]]
def hasLast[A](assertion: Assertion[A]): Assertion[Seq[A]]
// Set operations
def isSubsetOf[A](superset: Set[A]): Assertion[Set[A]]
def isSupersetOf[A](subset: Set[A]): Assertion[Set[A]]
def intersects[A](other: Set[A]): Assertion[Set[A]]
// Map operations
def hasKey[K](key: K): Assertion[Map[K, Any]]
def hasValue[V](value: V): Assertion[Map[Any, V]]
def hasKeyValue[K, V](key: K, value: V): Assertion[Map[K, V]]Usage Examples:
import zio.test.Assertion._
val numbers = List(1, 2, 3, 4, 5)
val words = List("apple", "banana", "cherry")
// Size assertions
assert(numbers)(hasSize(equalTo(5)))
assert(List.empty[Int])(isEmpty)
// Element membership
assert(numbers)(contains(3))
assert(words)(containsAll("apple", "cherry"))
assert(numbers)(exists(isGreaterThan(3)))
assert(numbers)(forall(isGreaterThan(0)))
// Sequence operations
assert(numbers)(startsWith(Seq(1, 2)))
assert(words)(hasFirst(equalTo("apple")))
assert(numbers)(hasAt(2)(equalTo(3)))
// Map operations
val userMap = Map("id" -> 123, "name" -> "Alice")
assert(userMap)(hasKey("name"))
assert(userMap)(hasKeyValue("id", 123))Specialized assertions for testing exceptions and ZIO effects.
// Exception assertions
def throws[E <: Throwable](assertion: Assertion[E]): Assertion[Any]
def throwsA[E <: Throwable](implicit tag: ClassTag[E]): Assertion[Any]
// ZIO effect assertions
def succeeds[A](assertion: Assertion[A]): Assertion[IO[Any, A]]
def fails[E](assertion: Assertion[E]): Assertion[IO[E, Any]]
def dies(assertion: Assertion[Throwable]): Assertion[Task[Any]]
def isInterrupted: Assertion[Task[Any]]
// Cause assertions
def failsCause[E](assertion: Assertion[Cause[E]]): Assertion[IO[E, Any]]
def diesCause(assertion: Assertion[Cause[Nothing]]): Assertion[Task[Any]]
// Numeric approximation
def approximatelyEquals[A](reference: A, tolerance: A)(implicit
num: Numeric[A]
): Assertion[A]
// Additional ZIO effect assertions
def isInterruptedOnly: Assertion[Task[Any]]
def completes: Assertion[ZIO[Any, Any, Any]]
def completesWithin(duration: Duration): Assertion[ZIO[Any, Any, Any]]Usage Examples:
import zio.test.Assertion._
// Exception testing
def divide(a: Int, b: Int): Int =
if (b == 0) throw new ArithmeticException("Division by zero")
else a / b
assert(divide(10, 0))(throws(isSubtype[ArithmeticException](anything)))
// ZIO effect testing
val successEffect = ZIO.succeed(42)
val failureEffect = ZIO.fail("error")
val dieEffect = ZIO.die(new RuntimeException("boom"))
assert(successEffect)(succeeds(equalTo(42)))
assert(failureEffect)(fails(equalTo("error")))
assert(dieEffect)(dies(isSubtype[RuntimeException](anything)))Assertions for testing object properties and fields.
/**
* Assert on a field of an object
* @param name field name (for error reporting)
* @param proj projection function to extract field value
* @param assertion assertion to apply to field value
*/
def hasField[A, B](name: String, proj: A => B, assertion: Assertion[B]): Assertion[A]
/**
* Convenience method for testing case class fields by name
*/
def hasField[A, B](name: String, assertion: Assertion[B])(implicit proj: A => B): Assertion[A]Usage Examples:
import zio.test.Assertion._
case class User(id: Int, name: String, email: String, active: Boolean)
val user = User(123, "Alice", "alice@example.com", true)
// Field assertions
assert(user)(hasField("id", _.id, equalTo(123)))
assert(user)(hasField("name", _.name, startsWith("A")))
assert(user)(hasField("active", _.active, isTrue))
// Combined field assertions
assert(user)(
hasField("id", _.id, isGreaterThan(0)) &&
hasField("name", _.name, isNonEmptyString) &&
hasField("email", _.email, matchesRegex(".*@.*".r))
)Core type representing the outcome of test assertions.
/**
* Result of a test assertion
*/
trait TestResult {
/**
* True if the test succeeded
*/
def isSuccess: Boolean
/**
* True if the test failed
*/
def isFailure: Boolean
/**
* Add a custom message to this result
* @param message descriptive message
* @return test result with message
*/
def ??(message: String): TestResult
/**
* Combine with another test result using logical AND
*/
def &&(that: TestResult): TestResult
/**
* Combine with another test result using logical OR
*/
def ||(that: TestResult): TestResult
/**
* Negate this test result
*/
def unary_! : TestResult
}
object TestResult {
case class Succeeded(result: BoolAlgebra[AssertionValue]) extends TestResult
case class Failed(result: BoolAlgebra[AssertionValue]) extends TestResult
val succeed: TestResult
val fail: TestResult
}/**
* Represents test failures with detailed information
*/
sealed trait TestFailure[+E] {
def map[E1](f: E => E1): TestFailure[E1]
}
object TestFailure {
case class Assertion(result: TestResult) extends TestFailure[Nothing]
case class Runtime[E](cause: Cause[E]) extends TestFailure[E]
}
/**
* Represents successful test completion
*/
case class TestSuccess() extends AnyVal