ZIO Test is a zero-dependency testing library that makes it easy to test effectual programs
Core DSL for creating tests and test suites with support for nested suites, test organization, and ZIO effect integration.
Creates a single test case with a descriptive label and assertion.
/**
* Creates a test with the specified label and assertion
* @param label descriptive name for the test
* @param assertion test logic returning TestResult or ZIO effect
* @return test specification
*/
def test[R](label: String)(assertion: => ZIO[R, Any, TestResult]): Spec[R, Any]Usage Examples:
import zio.test._
// Simple test with assertTrue
test("addition works correctly") {
assertTrue(2 + 2 == 4)
}
// Effectful test
test("database connection") {
for {
connection <- Database.connect
isValid <- connection.isValid
} yield assertTrue(isValid)
}
// Test with custom assertion
test("list contains element") {
val list = List(1, 2, 3, 4, 5)
assert(list)(contains(3))
}Creates a test suite containing multiple tests or nested suites.
/**
* Creates a test suite with the specified label and child specifications
* @param label descriptive name for the suite
* @param specs child test specifications (tests or nested suites)
* @return suite specification
*/
def suite[R](label: String)(specs: Spec[R, Any]*): Spec[R, Any]Usage Examples:
import zio.test._
// Simple suite with multiple tests
suite("Math Operations")(
test("addition") { assertTrue(2 + 2 == 4) },
test("multiplication") { assertTrue(3 * 4 == 12) },
test("division") { assertTrue(10 / 2 == 5) }
)
// Nested suites
suite("API Tests")(
suite("User Endpoints")(
test("create user") { /* test logic */ },
test("get user") { /* test logic */ },
test("update user") { /* test logic */ }
),
suite("Product Endpoints")(
test("list products") { /* test logic */ },
test("create product") { /* test logic */ }
)
)Low-level effectful test type for advanced test construction.
/**
* Effectful test that may fail with TestFailure[E] or succeed with TestSuccess
*/
type ZTest[-R, +E] = ZIO[R, TestFailure[E], TestSuccess]
object ZTest {
/**
* Builds a test with an effectual assertion
* @param label test label
* @param assertion effectual test assertion
* @return ZTest instance
*/
def apply[R, E](label: String, assertion: => ZIO[R, E, TestResult]): ZIO[R, TestFailure[E], TestSuccess]
}Core specification type supporting composition and test aspect application.
/**
* A test specification that can be executed to produce test results
* @tparam R environment required to run the specification
* @tparam E error type that tests may fail with
*/
trait Spec[+R, +E] {
/**
* Apply a test aspect to this specification
* @param aspect test aspect to apply
* @return modified specification
*/
def @@[R1 <: R](aspect: TestAspect[Nothing, R1, Nothing, Any]): Spec[R1, E]
/**
* Transform the environment of this specification
* @param f transformation function
* @return specification with transformed environment
*/
def provideLayer[R0, R1, E1 >: E](layer: ZLayer[R0, E1, R1]): Spec[R0, E1]
}Usage Examples:
import zio.test._
import zio.test.TestAspect._
// Apply timeout aspect to entire suite
suite("Database Tests")(
test("slow query") { /* test logic */ },
test("batch insert") { /* test logic */ }
) @@ timeout(30.seconds)
// Apply multiple aspects
suite("Integration Tests")(
test("external API call") { /* test logic */ }
) @@ timeout(10.seconds) @@ eventually @@ flakyIndividual test case within a specification.
/**
* A single test case with metadata
* @param label descriptive test name
* @param test the test logic as ZIO effect
* @param annotations metadata attached to the test
*/
case class SpecCase[+R, +E](
label: String,
test: ZIO[R, TestFailure[E], TestSuccess],
annotations: TestAnnotationMap
)Base classes for creating test suites with standard patterns.
/**
* Abstract base class for ZIO test specifications
* @tparam R environment type required by tests
*/
abstract class ZIOSpec[R] {
/**
* The test specification to execute
*/
def spec: Spec[R, Any]
}
/**
* Base class for test specs with standard test environment
*/
abstract class ZIOSpecDefault extends ZIOSpec[TestEnvironment] {
/**
* Test specification using default test environment
*/
def spec: Spec[TestEnvironment, Any]
}Usage Examples:
import zio.test._
// Using ZIOSpecDefault (recommended)
object MyTestSpec extends ZIOSpecDefault {
def spec = suite("My Tests")(
test("basic test") {
assertTrue(1 + 1 == 2)
}
)
}
// Using ZIOSpec with custom environment
object CustomEnvSpec extends ZIOSpec[MyCustomEnv] {
def spec = suite("Custom Environment Tests")(
test("uses custom service") {
for {
result <- ZIO.serviceWithZIO[MyCustomService](_.doSomething())
} yield assertTrue(result.isSuccess)
}
)
}Type class for constructing suites from various input types.
/**
* Type class for constructing test suites from different input types
*/
trait SuiteConstructor[In] {
type OutEnvironment
type OutError
def apply(in: In): Spec[OutEnvironment, OutError]
}
// Instances for common types
implicit def functionSuiteConstructor[A, In](implicit
constructor: TestConstructor[In]
): SuiteConstructor[A => In]
implicit def specSuiteConstructor[R, E]: SuiteConstructor[Spec[R, E]]/**
* Interface for running test specifications
*/
trait TestRunner[R, E] {
def run(spec: Spec[R, E]): ZIO[R, Nothing, ExecutionEvent]
}
object TestRunner {
def default[R, E]: TestRunner[R, E]
}/**
* Events emitted during test execution
*/
sealed trait ExecutionEvent
case class Test(labels: List[String], test: Either[TestFailure[Any], TestSuccess]) extends 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[E](labels: List[String], result: Either[TestFailure[E], TestSuccess]) extends ExecutionEventInstall with Tessl CLI
npx tessl i tessl/maven-dev-zio--zio-test-2-12