0
# Test Specifications
1
2
Core DSL for defining test suites and individual tests with full ZIO integration and composition support.
3
4
## Capabilities
5
6
### Test Creation Functions
7
8
Creates individual test cases with assertions.
9
10
```scala { .api }
11
/**
12
* Creates a pure test with the specified label and assertion
13
* @param label - Descriptive name for the test
14
* @param assertion - Test assertion that produces a TestResult
15
* @returns A test specification that can be run
16
*/
17
def test(label: String)(assertion: => TestResult)(implicit loc: SourceLocation): ZSpec[Any, Nothing]
18
19
/**
20
* Creates an effectful test with the specified label and ZIO-based assertion
21
* @param label - Descriptive name for the test
22
* @param assertion - ZIO effect that produces a TestResult
23
* @returns A test specification with environment and error requirements
24
*/
25
def testM[R, E](label: String)(assertion: => ZIO[R, E, TestResult])(implicit loc: SourceLocation): ZSpec[R, E]
26
```
27
28
**Usage Examples:**
29
30
```scala
31
import zio.test._
32
import zio.test.Assertion._
33
34
test("string length") {
35
assert("hello")(hasSize(equalTo(5)))
36
}
37
38
testM("async operation") {
39
for {
40
result <- someAsyncOperation
41
} yield assert(result)(isSuccess)
42
}
43
```
44
45
### Suite Creation Functions
46
47
Creates test suites that group related tests together.
48
49
```scala { .api }
50
/**
51
* Creates a test suite containing multiple specs
52
* @param label - Descriptive name for the suite
53
* @param specs - Variable number of test specifications
54
* @returns Combined test specification
55
*/
56
def suite[R, E, T](label: String)(specs: Spec[R, E, T]*): Spec[R, E, T]
57
58
/**
59
* Creates an effectful test suite with specs computed at runtime
60
* @param label - Descriptive name for the suite
61
* @param specs - ZIO effect that produces an iterable of specs
62
* @returns Test specification that executes specs when computed
63
*/
64
def suiteM[R, E, T](label: String)(specs: ZIO[R, E, Iterable[Spec[R, E, T]]]): Spec[R, E, T]
65
```
66
67
**Usage Examples:**
68
69
```scala
70
suite("Calculator Tests")(
71
test("addition") {
72
assert(2 + 2)(equalTo(4))
73
},
74
test("subtraction") {
75
assert(5 - 3)(equalTo(2))
76
}
77
)
78
79
suiteM("Dynamic Tests") {
80
ZIO.succeed(List(
81
test("test 1")(assert(true)(isTrue)),
82
test("test 2")(assert(false)(isFalse))
83
))
84
}
85
```
86
87
### Spec Class and Composition
88
89
The core `Spec` type that represents test specifications.
90
91
```scala { .api }
92
/**
93
* Core specification type that can be a suite or individual test
94
* @tparam R - Environment requirements
95
* @tparam E - Error type
96
* @tparam T - Test result type
97
*/
98
case class Spec[-R, +E, +T](caseValue: SpecCase[R, E, T, Spec[R, E, T]]) {
99
/** Combines this spec with another spec */
100
def +[R1 <: R, E1 >: E, T1 >: T](that: Spec[R1, E1, T1]): Spec[R1, E1, T1]
101
102
/** Applies a test aspect to transform behavior */
103
def @@[R0 <: R1, R1 <: R, E0, E1, E2 >: E0 <: E1](
104
aspect: TestAspect[R0, R1, E0, E1]
105
)(implicit ev1: E <:< TestFailure[E2], ev2: T <:< TestSuccess): ZSpec[R1, E2]
106
107
/** Adds annotation to the spec */
108
def annotate[V](key: TestAnnotation[V], value: V): Spec[R, Annotated[E], Annotated[T]]
109
110
/** Filters specs based on tags */
111
def filterTags(predicate: Set[String] => Boolean): Spec[R, E, T]
112
113
/** Provides environment layer to the spec */
114
def provideCustomLayer[E1 >: E, R0](layer: ZLayer[R0, E1, R]): Spec[R0, E1, T]
115
116
/** Transforms the spec structure */
117
def transform[R1, E1, T1](
118
f: SpecCase[R, E, T, Spec[R, E, T]] => SpecCase[R1, E1, T1, Spec[R1, E1, T1]]
119
): Spec[R1, E1, T1]
120
}
121
```
122
123
### Spec Companion Object
124
125
Factory methods for creating different types of specifications.
126
127
```scala { .api }
128
object Spec {
129
/** Creates a labeled spec */
130
def labeled[R, E, T](label: String, spec: Spec[R, E, T]): Spec[R, E, T]
131
132
/** Combines multiple specs into one */
133
def multiple[R, E, T](specs: Chunk[Spec[R, E, T]]): Spec[R, E, T]
134
135
/** Creates a spec from a test case */
136
def test[R, E, T](test: T, annotations: TestAnnotationMap): Spec[R, E, T]
137
138
/** Creates a spec that uses managed resources */
139
def managed[R, E, T](spec: Managed[E, Spec[R, E, T]]): Spec[R, E, T]
140
}
141
```
142
143
## Type Aliases
144
145
```scala { .api }
146
/**
147
* A test that requires environment R and may fail with error E
148
*/
149
type ZTest[-R, +E] = ZIO[R, TestFailure[E], TestSuccess]
150
151
/**
152
* A test specification for ZIO programs
153
*/
154
type ZSpec[-R, +E] = Spec[R, TestFailure[E], TestSuccess]
155
156
/**
157
* An annotated value containing test metadata
158
*/
159
type Annotated[+A] = (A, TestAnnotationMap)
160
```
161
162
## Complete Example
163
164
```scala
165
import zio.test._
166
import zio.test.Assertion._
167
import zio.test.environment.TestEnvironment
168
169
object CompleteSpecExample extends DefaultRunnableSpec {
170
def spec = suite("Complete Example")(
171
suite("Basic Tests")(
172
test("simple assertion") {
173
assert(2 + 2)(equalTo(4))
174
},
175
testM("effectful test") {
176
for {
177
value <- ZIO.succeed(42)
178
} yield assert(value)(isGreaterThan(40))
179
}
180
),
181
182
suite("Advanced Tests")(
183
test("multiple assertions") {
184
assertTrue(
185
"hello".length == 5,
186
List(1, 2, 3).size == 3,
187
Some(42).isDefined
188
)
189
}
190
) @@ TestAspect.parallel,
191
192
test("ignored test") {
193
assert(false)(isTrue)
194
} @@ TestAspect.ignore
195
)
196
}
197
```