0
# ZIO Test
1
2
ZIO Test is a featherweight testing library for effectful programs. It treats every test specification as an immutable value, enabling powerful composition and transformation capabilities. The library provides tight integration with ZIO effects, allowing developers to test asynchronous and complex computational workflows naturally without the need for complex async value wrapping or multiple unsafeRun calls.
3
4
## Package Information
5
6
- **Package Name**: zio-test
7
- **Package Type**: maven
8
- **Language**: Scala
9
- **Installation**: `libraryDependencies += "dev.zio" %% "zio-test" % "1.0.18"`
10
11
## Core Imports
12
13
```scala
14
import zio.test._
15
import zio.test.Assertion._
16
import zio.test.environment._
17
```
18
19
For specific functionality:
20
21
```scala
22
// Core testing DSL
23
import zio.test.{test, testM, suite, assert, assertM, assertTrue}
24
25
// Assertions
26
import zio.test.Assertion.{equalTo, isTrue, contains, hasSize}
27
28
// Property testing
29
import zio.test.{Gen, check, checkAll}
30
31
// Test environment
32
import zio.test.environment.{TestEnvironment, TestClock, TestConsole, TestRandom}
33
34
// Runnable specs
35
import zio.test.DefaultRunnableSpec
36
```
37
38
## Basic Usage
39
40
```scala
41
import zio.test._
42
import zio.test.Assertion._
43
import zio.test.environment._
44
45
object MyTestSpec extends DefaultRunnableSpec {
46
def spec = suite("My Test Suite")(
47
test("basic assertion") {
48
assert(2 + 2)(equalTo(4))
49
},
50
testM("effectful test") {
51
for {
52
result <- ZIO.succeed(42)
53
} yield assert(result)(equalTo(42))
54
},
55
test("boolean assertion") {
56
assertTrue(2 + 2 == 4, "hello".length == 5)
57
}
58
)
59
}
60
```
61
62
## Architecture
63
64
ZIO Test is built around several key components:
65
66
- **Test Specifications**: `Spec` and `ZSpec` types that compose into test suites and individual tests
67
- **Assertion System**: Rich assertion library with composable assertions and detailed failure reporting
68
- **Property Testing**: `Gen` generators with automatic shrinking for property-based testing
69
- **Test Environment**: Controllable versions of ZIO services (Clock, Console, Random, System) for deterministic testing
70
- **Test Execution**: Runners and executors for running test suites with configurable behavior
71
- **Mocking Framework**: Complete mocking system for testing with controlled dependencies
72
- **Test Aspects**: Composable transformations for test behavior (retry, timeout, parallel execution, etc.)
73
74
## Capabilities
75
76
### Test Specifications
77
78
Core DSL for defining test suites and individual tests with full ZIO integration and composition support.
79
80
```scala { .api }
81
def test(label: String)(assertion: => TestResult)(implicit loc: SourceLocation): ZSpec[Any, Nothing]
82
def testM[R, E](label: String)(assertion: => ZIO[R, E, TestResult])(implicit loc: SourceLocation): ZSpec[R, E]
83
def suite[R, E, T](label: String)(specs: Spec[R, E, T]*): Spec[R, E, T]
84
def suiteM[R, E, T](label: String)(specs: ZIO[R, E, Iterable[Spec[R, E, T]]]): Spec[R, E, T]
85
```
86
87
[Test Specifications](./test-specifications.md)
88
89
### Assertion Framework
90
91
Rich assertion system with over 50 built-in assertions, logical combinators, and detailed failure reporting.
92
93
```scala { .api }
94
def assert[A](value: => A)(assertion: Assertion[A]): TestResult
95
def assertM[R, E, A](effect: ZIO[R, E, A])(assertion: AssertionM[A]): ZIO[R, E, TestResult]
96
def assertTrue(exprs: Boolean*): TestResult
97
98
trait Assertion[A] {
99
def run(actual: A): AssertResult
100
def &&(that: Assertion[A]): Assertion[A]
101
def ||(that: Assertion[A]): Assertion[A]
102
def unary_!: Assertion[A]
103
}
104
```
105
106
[Assertion Framework](./assertions.md)
107
108
### Property Testing
109
110
Comprehensive property-based testing with generators, automatic shrinking, and configurable test execution.
111
112
```scala { .api }
113
def check[R <: TestConfig, A](rv: Gen[R, A])(test: A => TestResult): URIO[R, TestResult]
114
def checkM[R <: TestConfig, R1 <: R, E, A](rv: Gen[R, A])(test: A => ZIO[R1, E, TestResult]): ZIO[R1, E, TestResult]
115
def checkAll[R <: TestConfig, A](rv: Gen[R, A])(test: A => TestResult): URIO[R, TestResult]
116
117
abstract class Gen[-R, +A] {
118
def map[B](f: A => B): Gen[R, B]
119
def flatMap[R1 <: R, B](f: A => Gen[R1, B]): Gen[R1, B]
120
def filter(f: A => Boolean): Gen[R, A]
121
}
122
```
123
124
[Property Testing](./property-testing.md)
125
126
### Test Environment
127
128
Controllable test services that replace ZIO's standard environment for deterministic testing.
129
130
```scala { .api }
131
object TestClock {
132
def adjust(duration: Duration): URIO[TestClock, Unit]
133
def setDateTime(dateTime: OffsetDateTime): URIO[TestClock, Unit]
134
def setTime(duration: Duration): URIO[TestClock, Unit]
135
def sleeps: URIO[TestClock, List[Duration]]
136
}
137
138
object TestConsole {
139
def feedLines(lines: String*): URIO[TestConsole, Unit]
140
def output: URIO[TestConsole, Vector[String]]
141
def clearOutput: URIO[TestConsole, Unit]
142
def clearInput: URIO[TestConsole, Unit]
143
}
144
145
object TestRandom {
146
def feedInts(ints: Int*): URIO[TestRandom, Unit]
147
def feedDoubles(doubles: Double*): URIO[TestRandom, Unit]
148
def setSeed(seed: Long): URIO[TestRandom, Unit]
149
}
150
151
object TestSystem {
152
def putProperty(name: String, value: String): URIO[TestSystem, Unit]
153
def putEnv(name: String, value: String): URIO[TestSystem, Unit]
154
def clearProperty(prop: String): URIO[TestSystem, Unit]
155
def clearEnv(variable: String): URIO[TestSystem, Unit]
156
}
157
```
158
159
[Test Environment](./test-environment.md)
160
161
### Mocking Framework
162
163
Complete mocking system for creating controlled test doubles with expectation-based verification.
164
165
```scala { .api }
166
abstract class Mock[-M <: Has[_]] {
167
def expects[I, A](capability: Capability[M, I, A]): Expectation[I]
168
}
169
170
sealed trait Expectation[-I] {
171
def and[I1 <: I](that: Expectation[I1]): Expectation[I1]
172
def repeats(range: Range): Expectation[I]
173
def returns[A](value: A): Expectation[I]
174
def returnsM[R, E, A](effect: ZIO[R, E, A]): Expectation[I]
175
}
176
```
177
178
[Mocking Framework](./mocking.md)
179
180
### Test Execution
181
182
Test runners and executors for running test suites with configurable behavior and reporting.
183
184
```scala { .api }
185
case class TestRunner[+R, -E](executor: TestExecutor[R, E]) {
186
def run[R1 <: R, E1 >: E](spec: ZSpec[R1, E1]): URIO[R1, ExecutedSpec[E1]]
187
}
188
189
abstract class DefaultRunnableSpec extends RunnableSpec[TestEnvironment, Any] {
190
def spec: ZSpec[TestEnvironment, Any]
191
}
192
```
193
194
[Test Execution](./test-execution.md)
195
196
### Test Aspects
197
198
Composable test transformations for modifying test behavior including retry, timeout, and parallel execution.
199
200
```scala { .api }
201
abstract class TestAspect[+LowerR, -UpperR, +LowerE, -UpperE] {
202
def apply[R, E](spec: ZSpec[R, E]): ZSpec[R, E]
203
}
204
205
// Control aspects
206
val ignore: TestAspectPoly
207
val flaky: TestAspectPoly
208
val parallel: TestAspectPoly
209
def timeout(duration: Duration): TestAspectAtLeastR[Live]
210
def eventually: TestAspectAtLeastR[Live with Annotations]
211
212
// Configuration aspects
213
def samples(n: Int): TestAspectAtLeastR[TestConfig]
214
def shrinks(n: Int): TestAspectAtLeastR[TestConfig]
215
def repeats(n: Int): TestAspectAtLeastR[TestConfig]
216
def retries(n: Int): TestAspectAtLeastR[TestConfig]
217
218
// Lifecycle aspects
219
def before[R](effect: ZIO[R, Nothing, Any]): TestAspectAtLeastR[R]
220
def after[R](effect: ZIO[R, Nothing, Any]): TestAspectAtLeastR[R]
221
def around[R, A](before: ZIO[R, Nothing, A])(after: A => ZIO[R, Nothing, Any]): TestAspectAtLeastR[R]
222
```
223
224
[Test Aspects](./test-aspects.md)
225
226
## Types
227
228
```scala { .api }
229
type ZTest[-R, +E] = ZIO[R, TestFailure[E], TestSuccess]
230
type ZSpec[-R, +E] = Spec[R, TestFailure[E], TestSuccess]
231
type TestResult = BoolAlgebra[AssertionResult]
232
type ZTestEnv = TestClock with TestConsole with TestRandom with TestSystem
233
type TestEnvironment = ZTestEnv with Live
234
type Annotated[+A] = (A, TestAnnotationMap)
235
236
// Core service types
237
type TestConfig = Has[TestConfig.Service]
238
type Annotations = Has[Annotations.Service]
239
type Sized = Has[Sized.Service]
240
type TestLogger = Has[TestLogger.Service]
241
242
// Aspect type aliases
243
type TestAspectPoly = TestAspect[Nothing, Any, Nothing, Any]
244
type TestAspectAtLeastR[R] = TestAspect[Nothing, R, Nothing, Any]
245
246
case class Spec[-R, +E, +T](caseValue: SpecCase[R, E, T, Spec[R, E, T]])
247
248
sealed trait TestSuccess
249
object TestSuccess {
250
case class Succeeded(result: BoolAlgebra[Unit]) extends TestSuccess
251
case object Ignored extends TestSuccess
252
}
253
254
sealed trait TestFailure[+E]
255
object TestFailure {
256
case class Assertion(result: BoolAlgebra[AssertionResult]) extends TestFailure[Nothing]
257
case class Runtime[+E](cause: Cause[E]) extends TestFailure[E]
258
}
259
```