or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

assertions.mdconfiguration.mdindex.mdproperty-testing.mdtest-aspects.mdtest-definition.mdtest-services.md
tile.json

tessl/maven-dev-zio--zio-test

ZIO Test is a zero-dependency testing library that makes it easy to test effectual programs

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/dev.zio/zio-test_2.12@2.1.x

To install, run

npx @tessl/cli install tessl/maven-dev-zio--zio-test@2.1.0

index.mddocs/

ZIO Test

ZIO Test is a comprehensive testing framework for effectual Scala programs built with ZIO. It provides zero-dependency testing with advanced features including property-based testing, sophisticated assertions, test aspects for cross-cutting concerns, and deterministic test services for reliable testing of concurrent and asynchronous code.

Package Information

  • Package Name: zio-test
  • Package Type: maven
  • Language: Scala
  • Installation: libraryDependencies += "dev.zio" %% "zio-test" % "2.1.19"
  • Test Integration: libraryDependencies += "dev.zio" %% "zio-test-sbt" % "2.1.19" % Test

Core Imports

import zio.test._
import zio.test.Assertion._
import zio.test.Gen._

For specific functionality:

// Property-based testing
import zio.test.{Gen, check, checkAll}

// Test aspects
import zio.test.TestAspect.{timeout, parallel, eventually}

// Test services
import zio.test.{TestClock, TestConsole, TestRandom, TestSystem}

// Advanced features
import zio.test.laws._      // Laws-based property testing
import zio.test.diff._      // Value differencing system
import zio.test.render._    // Test result rendering
import zio.test.poly._      // Polymorphic generators

Basic Usage

import zio.test._
import zio.test.Assertion._

object BasicExampleSpec extends ZIOSpecDefault {
  def spec = suite("Basic Examples")(
    test("simple assertion") {
      val result = 2 + 2
      assertTrue(result == 4)
    },
    
    test("ZIO effect testing") {
      for {
        time <- zio.Clock.currentTime(java.util.concurrent.TimeUnit.MILLISECONDS)
      } yield assertTrue(time > 0L)
    },
    
    test("property-based testing") {
      check(Gen.int) { n =>
        assertTrue((n + n) == (n * 2))
      }
    }
  )
}

Architecture

ZIO Test is built around several key components:

  • Test Definition DSL: test, suite, ZTest for creating test specifications
  • Assertion System: Rich set of combinable assertions with detailed failure reporting
  • Property-Based Testing: Comprehensive generator system with automatic shrinking
  • Test Aspects: Cross-cutting concerns like timeouts, retries, parallelism, and platform-specific execution
  • Deterministic Services: TestClock, TestConsole, TestRandom, TestSystem for predictable testing
  • Test Environment: Layered dependency injection system for test services and configuration
  • Execution Engine: Parallel and sequential test execution with comprehensive reporting

Capabilities

Test Definition and Structure

Core DSL for creating tests and test suites with support for nested suites, test organization, and ZIO effect integration.

def test[R](label: String)(assertion: => ZIO[R, Any, TestResult]): Spec[R, Any]
def suite[R](label: String)(specs: Spec[R, Any]*): Spec[R, Any]

trait Spec[+R, +E] {
  def @@[R1 <: R](aspect: TestAspect[Nothing, R1, Nothing, Any]): Spec[R1, E]
}

type ZTest[-R, +E] = ZIO[R, TestFailure[E], TestSuccess]

// Base classes for test specifications
abstract class ZIOSpec[R] {
  def spec: Spec[R, Any]
}

abstract class ZIOSpecDefault extends ZIOSpec[TestEnvironment] {
  def spec: Spec[TestEnvironment, Any]
}

abstract class ZIOSpecAbstract[R](implicit trace: Trace) extends ZIOSpec[R] {
  def spec: Spec[R, Any]
}

Test Definition and Structure

Assertions and Test Results

Comprehensive assertion library with combinable assertions, smart error messages, and detailed failure reporting.

def assertTrue(exprs: Boolean*): TestResult
def assert[A](expr: => A)(assertion: Assertion[A]): TestResult
def assertZIO[R, E, A](effect: ZIO[R, E, A])(assertion: Assertion[A]): ZIO[R, E, TestResult]

trait Assertion[-A] {
  def apply(value: A): TestResult
  def &&(that: Assertion[A]): Assertion[A]
  def ||(that: Assertion[A]): Assertion[A]
  def unary_! : Assertion[A]
}

// Core assertion functions
def equalTo[A](expected: A): Assertion[A]
def isTrue: Assertion[Boolean]
def contains[A](element: A): Assertion[Iterable[A]]
def hasSize[A](assertion: Assertion[Int]): Assertion[Iterable[A]]

Assertions and Test Results

Property-Based Testing

Advanced property-based testing with sophisticated generators, automatic shrinking, and configurable test execution.

def check[R <: ZAny, A](rv: Gen[R, A])(test: A => TestResult): ZIO[R with TestConfig, Nothing, TestResult]
def checkAll[R <: ZAny, A](rv: Gen[R, A])(test: A => TestResult): ZIO[R with TestConfig, Nothing, TestResult]

trait Gen[+R, +A] {
  def map[B](f: A => B): Gen[R, B]
  def flatMap[R1 <: R, B](f: A => Gen[R1, B]): Gen[R1, B]
  def filter(f: A => Boolean): Gen[R, A]
  def sample: ZStream[R, Nothing, Sample[R, A]]
}

// Generator constructors
val anyInt: Gen[Any, Int]
val anyString: Gen[Any, String]
def listOfN[R, A](n: Int)(g: Gen[R, A]): Gen[R, List[A]]
def oneOf[R, A](first: Gen[R, A], rest: Gen[R, A]*): Gen[R, A]

Property-Based Testing

Test Aspects

Cross-cutting concerns for test execution including timeouts, retries, parallelism, and platform-specific behavior.

trait TestAspect[-LowerR, +UpperR, -LowerE, +UpperE] {
  def apply[R >: LowerR <: UpperR, E >: LowerE <: UpperE](
    spec: Spec[R, E]
  ): Spec[R, E]
}

// Common test aspects
object TestAspect {
  def timeout(duration: Duration): TestAspectAtLeastR[Live]
  val parallel: TestAspectPoly
  val sequential: TestAspectPoly
  val eventually: TestAspectAtLeastR[Live]
  val flaky: TestAspectPoly
  val ignore: TestAspectPoly
  val js: TestAspectPoly
  val jvm: TestAspectPoly
}

Test Aspects

Test Services

Deterministic test services that replace system services during testing for predictable, reproducible test execution.

trait TestClock extends Clock {
  def adjust(duration: Duration): UIO[Unit]
  def setTime(duration: Duration): UIO[Unit]
  def timeZone: UIO[ZoneId]
}

trait TestConsole extends Console {
  def output: UIO[Vector[String]]
  def clearOutput: UIO[Unit]
  def feedLines(lines: String*): UIO[Unit]
}

trait TestRandom extends Random {
  def setSeed(seed: Long): UIO[Unit]
  def feedBooleans(booleans: Boolean*): UIO[Unit]
  def clearBooleans: UIO[Unit]
}

trait TestSystem extends System {
  def putEnv(name: String, value: String): UIO[Unit]
  def putProperty(name: String, value: String): UIO[Unit]
}

Test Services

Test Configuration and Environment

Configuration system for controlling test execution parameters and environment setup for dependency injection.

trait TestConfig {
  def repeats: Int
  def retries: Int
  def samples: Int
  def shrinks: Int
}

type TestEnvironment = Annotations with Live with Sized with TestConfig

object TestEnvironment {
  val live: ZLayer[Clock with Console with System with Random, Nothing, TestEnvironment]
}

val testEnvironment: ZLayer[Any, Nothing, TestEnvironment]

Configuration and Environment

Laws-Based Property Testing

Advanced property-based testing using mathematical laws and algebraic properties for typeclass verification.

trait Laws[Caps, R] {
  def laws: List[ZLaws[Caps, R]]
}

trait ZLaws[-Caps, -R] {
  def run[R1 <: R, A](implicit
    checkConstructor: CheckConstructor[R1],
    caps: Caps,
    gen: GenF[R1, A]
  ): URIO[R1, TestResult]
}

object Laws {
  def derive[F[_], Caps, R](implicit
    laws: Laws[Caps, R]
  ): ZLaws[Caps, R]
}

Value Differencing System

System for computing and rendering differences between values for enhanced test failure reporting.

trait Diff[A] {
  def apply(x: A, y: A): DiffResult
}

sealed trait DiffResult {
  def render: String
  def isIdentical: Boolean
}

object Diff {
  val string: Diff[String]
  val boolean: Diff[Boolean]
  val int: Diff[Int]
  def option[A](implicit diff: Diff[A]): Diff[Option[A]]
  def either[A, B](implicit diffA: Diff[A], diffB: Diff[B]): Diff[Either[A, B]]
}

Test Execution and Reporting

System for running tests and collecting results with support for various execution strategies and event handling.

trait TestRunner[R, E] {
  def run(spec: Spec[R, E]): ZIO[R, Nothing, Summary]
}

trait TestExecutor[R, E] {
  def run(spec: Spec[R, E], defExec: ExecutionStrategy): ZIO[R, Nothing, ExecutionResult[E]]
}

object TestRunner {
  def default[R, E]: TestRunner[R, E]
}

// Execution events
sealed trait ExecutionEvent
case class SuiteStarted(labels: List[String]) extends ExecutionEvent
case class SuiteCompleted(labels: List[String]) extends ExecutionEvent  
case class TestStarted(labels: List[String]) extends ExecutionEvent
case class TestCompleted(labels: List[String], result: TestResult) extends ExecutionEvent

// Test results and summaries
case class Summary(
  success: Int,
  fail: Int, 
  ignore: Int,
  failureDetails: String
) {
  def total: Int = success + fail + ignore
}

sealed trait ExecutionStrategy
object ExecutionStrategy {
  case object Sequential extends ExecutionStrategy
  case object Parallel extends ExecutionStrategy
}

Types

// Core test types
trait TestResult {
  def isSuccess: Boolean
  def isFailure: Boolean
  def ??(message: String): TestResult
}

sealed trait TestFailure[+E] {
  def &&[E1 >: E](that: TestFailure[E1]): TestFailure[E1]
  def ||[E1 >: E](that: TestFailure[E1]): TestFailure[E1]
  def unary_! : TestFailure[E]
}

case class TestSuccess() extends AnyVal

// Diff system types
trait Diff[A] {
  def apply(x: A, y: A): DiffResult
}

sealed trait DiffResult {
  def render: String
}

// Test trace for debugging
case class TestTrace(
  rendered: String,
  span: Span
)

// Test structure types  
trait Spec[+R, +E]
case class SpecCase[+R, +E](
  label: String,
  test: ZIO[R, TestFailure[E], TestSuccess],
  annotations: TestAnnotationMap
)

// Sample and generation types
trait Sample[+R, +A] {
  def value: A
  def shrink: ZStream[R, Nothing, Sample[R, A]]
}

case class Sized(size: Int) extends AnyVal