0
# Assertions and Test Results
1
2
Comprehensive assertion library with combinable assertions, smart error messages, and detailed failure reporting.
3
4
## Capabilities
5
6
### Basic Assertion Functions
7
8
Simple assertion functions for common testing scenarios.
9
10
```scala { .api }
11
/**
12
* Assert that all boolean expressions are true
13
* @param exprs boolean expressions to evaluate
14
* @return test result indicating success or failure
15
*/
16
def assertTrue(exprs: Boolean*): TestResult
17
18
/**
19
* Assert a value against an assertion
20
* @param expr value to test
21
* @param assertion assertion to apply
22
* @return test result
23
*/
24
def assert[A](expr: => A)(assertion: Assertion[A]): TestResult
25
26
/**
27
* Assert an effectful computation against an assertion
28
* @param effect ZIO effect producing value to test
29
* @param assertion assertion to apply to the result
30
* @return effectful test result
31
*/
32
def assertZIO[R, E, A](effect: ZIO[R, E, A])(assertion: Assertion[A]): ZIO[R, E, TestResult]
33
34
/**
35
* Assert that a test completes successfully
36
*/
37
def assertCompletes: TestResult
38
39
/**
40
* Assert that a test never completes (useful for timeout testing)
41
* @param message descriptive failure message
42
*/
43
def assertNever(message: String): TestResult
44
```
45
46
**Usage Examples:**
47
48
```scala
49
import zio.test._
50
import zio.test.Assertion._
51
52
// Basic assertions
53
assertTrue(2 + 2 == 4)
54
assertTrue(List(1, 2, 3).nonEmpty, List(1, 2, 3).size == 3)
55
56
// Value assertions
57
assert(List(1, 2, 3))(hasSize(equalTo(3)))
58
assert("hello world")(startsWith("hello"))
59
assert(42)(isGreaterThan(0) && isLessThan(100))
60
61
// Effectful assertions
62
assertZIO(ZIO.succeed(List(1, 2, 3)))(contains(2))
63
assertZIO(database.getUser(123))(hasField("name", equalTo("Alice")))
64
```
65
66
### Assertion Trait
67
68
Core trait for building composable assertions.
69
70
```scala { .api }
71
/**
72
* An assertion that can be applied to values of type A
73
*/
74
trait Assertion[-A] {
75
/**
76
* Apply the assertion to a value
77
* @param value value to test
78
* @return test result
79
*/
80
def apply(value: A): TestResult
81
82
/**
83
* Combine with another assertion using logical AND
84
* @param that other assertion
85
* @return combined assertion
86
*/
87
def &&(that: Assertion[A]): Assertion[A]
88
89
/**
90
* Combine with another assertion using logical OR
91
* @param that other assertion
92
* @return combined assertion
93
*/
94
def ||(that: Assertion[A]): Assertion[A]
95
96
/**
97
* Negate this assertion
98
* @return negated assertion
99
*/
100
def unary_! : Assertion[A]
101
102
/**
103
* Add a custom label to this assertion
104
* @param message descriptive label
105
* @return labeled assertion
106
*/
107
def ??(message: String): Assertion[A]
108
}
109
```
110
111
### Core Assertion Functions
112
113
Fundamental assertion functions for common data types and operations.
114
115
```scala { .api }
116
// Equality and comparison
117
def equalTo[A](expected: A): Assertion[A]
118
def not[A](assertion: Assertion[A]): Assertion[A]
119
def anything: Assertion[Any]
120
def nothing: Assertion[Any]
121
122
// Boolean assertions
123
val isTrue: Assertion[Boolean]
124
val isFalse: Assertion[Boolean]
125
126
// Null/Option assertions
127
val isNull: Assertion[Any]
128
val isNonNull: Assertion[Any]
129
def isSome[A](assertion: Assertion[A]): Assertion[Option[A]]
130
val isNone: Assertion[Option[A]]
131
132
// Numeric comparisons
133
def isGreaterThan[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
134
def isGreaterThanEqualTo[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
135
def isLessThan[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
136
def isLessThanEqualTo[A](reference: A)(implicit ord: Ordering[A]): Assertion[A]
137
def isWithin[A](reference: A, tolerance: A)(implicit num: Numeric[A]): Assertion[A]
138
139
// String assertions
140
def startsWith(prefix: String): Assertion[String]
141
def endsWith(suffix: String): Assertion[String]
142
def containsString(substring: String): Assertion[String]
143
def matchesRegex(regex: Regex): Assertion[String]
144
def hasLength(assertion: Assertion[Int]): Assertion[String]
145
val isEmptyString: Assertion[String]
146
val isNonEmptyString: Assertion[String]
147
```
148
149
**Usage Examples:**
150
151
```scala
152
import zio.test.Assertion._
153
154
// Equality and comparison
155
assert(42)(equalTo(42))
156
assert("test")(not(equalTo("other")))
157
158
// Boolean
159
assert(true)(isTrue)
160
assert(false)(isFalse)
161
162
// Numeric
163
assert(10)(isGreaterThan(5))
164
assert(3.14)(isWithin(3.0, 0.2))
165
166
// String
167
assert("hello world")(startsWith("hello"))
168
assert("hello world")(endsWith("world"))
169
assert("hello world")(containsString("lo wo"))
170
assert("abc123")(matchesRegex("\\w+\\d+".r))
171
```
172
173
### Collection Assertions
174
175
Assertions for testing collections, iterables, and sequences.
176
177
```scala { .api }
178
// Size and emptiness
179
def hasSize[A](assertion: Assertion[Int]): Assertion[Iterable[A]]
180
val isEmpty: Assertion[Iterable[Any]]
181
val isNonEmpty: Assertion[Iterable[Any]]
182
183
// Element membership
184
def contains[A](element: A): Assertion[Iterable[A]]
185
def containsAll[A](elements: A*): Assertion[Iterable[A]]
186
def exists[A](assertion: Assertion[A]): Assertion[Iterable[A]]
187
def forall[A](assertion: Assertion[A]): Assertion[Iterable[A]]
188
189
// Sequence operations
190
def startsWith[A](prefix: Seq[A]): Assertion[Seq[A]]
191
def endsWith[A](suffix: Seq[A]): Assertion[Seq[A]]
192
def hasAt[A](index: Int)(assertion: Assertion[A]): Assertion[Seq[A]]
193
def hasFirst[A](assertion: Assertion[A]): Assertion[Seq[A]]
194
def hasLast[A](assertion: Assertion[A]): Assertion[Seq[A]]
195
196
// Set operations
197
def isSubsetOf[A](superset: Set[A]): Assertion[Set[A]]
198
def isSupersetOf[A](subset: Set[A]): Assertion[Set[A]]
199
def intersects[A](other: Set[A]): Assertion[Set[A]]
200
201
// Map operations
202
def hasKey[K](key: K): Assertion[Map[K, Any]]
203
def hasValue[V](value: V): Assertion[Map[Any, V]]
204
def hasKeyValue[K, V](key: K, value: V): Assertion[Map[K, V]]
205
```
206
207
**Usage Examples:**
208
209
```scala
210
import zio.test.Assertion._
211
212
val numbers = List(1, 2, 3, 4, 5)
213
val words = List("apple", "banana", "cherry")
214
215
// Size assertions
216
assert(numbers)(hasSize(equalTo(5)))
217
assert(List.empty[Int])(isEmpty)
218
219
// Element membership
220
assert(numbers)(contains(3))
221
assert(words)(containsAll("apple", "cherry"))
222
assert(numbers)(exists(isGreaterThan(3)))
223
assert(numbers)(forall(isGreaterThan(0)))
224
225
// Sequence operations
226
assert(numbers)(startsWith(Seq(1, 2)))
227
assert(words)(hasFirst(equalTo("apple")))
228
assert(numbers)(hasAt(2)(equalTo(3)))
229
230
// Map operations
231
val userMap = Map("id" -> 123, "name" -> "Alice")
232
assert(userMap)(hasKey("name"))
233
assert(userMap)(hasKeyValue("id", 123))
234
```
235
236
### Exception and Effect Assertions
237
238
Specialized assertions for testing exceptions and ZIO effects.
239
240
```scala { .api }
241
// Exception assertions
242
def throws[E <: Throwable](assertion: Assertion[E]): Assertion[Any]
243
def throwsA[E <: Throwable](implicit tag: ClassTag[E]): Assertion[Any]
244
245
// ZIO effect assertions
246
def succeeds[A](assertion: Assertion[A]): Assertion[IO[Any, A]]
247
def fails[E](assertion: Assertion[E]): Assertion[IO[E, Any]]
248
def dies(assertion: Assertion[Throwable]): Assertion[Task[Any]]
249
def isInterrupted: Assertion[Task[Any]]
250
251
// Cause assertions
252
def failsCause[E](assertion: Assertion[Cause[E]]): Assertion[IO[E, Any]]
253
def diesCause(assertion: Assertion[Cause[Nothing]]): Assertion[Task[Any]]
254
255
// Numeric approximation
256
def approximatelyEquals[A](reference: A, tolerance: A)(implicit
257
num: Numeric[A]
258
): Assertion[A]
259
260
// Additional ZIO effect assertions
261
def isInterruptedOnly: Assertion[Task[Any]]
262
def completes: Assertion[ZIO[Any, Any, Any]]
263
def completesWithin(duration: Duration): Assertion[ZIO[Any, Any, Any]]
264
```
265
266
**Usage Examples:**
267
268
```scala
269
import zio.test.Assertion._
270
271
// Exception testing
272
def divide(a: Int, b: Int): Int =
273
if (b == 0) throw new ArithmeticException("Division by zero")
274
else a / b
275
276
assert(divide(10, 0))(throws(isSubtype[ArithmeticException](anything)))
277
278
// ZIO effect testing
279
val successEffect = ZIO.succeed(42)
280
val failureEffect = ZIO.fail("error")
281
val dieEffect = ZIO.die(new RuntimeException("boom"))
282
283
assert(successEffect)(succeeds(equalTo(42)))
284
assert(failureEffect)(fails(equalTo("error")))
285
assert(dieEffect)(dies(isSubtype[RuntimeException](anything)))
286
```
287
288
### Object Field Assertions
289
290
Assertions for testing object properties and fields.
291
292
```scala { .api }
293
/**
294
* Assert on a field of an object
295
* @param name field name (for error reporting)
296
* @param proj projection function to extract field value
297
* @param assertion assertion to apply to field value
298
*/
299
def hasField[A, B](name: String, proj: A => B, assertion: Assertion[B]): Assertion[A]
300
301
/**
302
* Convenience method for testing case class fields by name
303
*/
304
def hasField[A, B](name: String, assertion: Assertion[B])(implicit proj: A => B): Assertion[A]
305
```
306
307
**Usage Examples:**
308
309
```scala
310
import zio.test.Assertion._
311
312
case class User(id: Int, name: String, email: String, active: Boolean)
313
314
val user = User(123, "Alice", "alice@example.com", true)
315
316
// Field assertions
317
assert(user)(hasField("id", _.id, equalTo(123)))
318
assert(user)(hasField("name", _.name, startsWith("A")))
319
assert(user)(hasField("active", _.active, isTrue))
320
321
// Combined field assertions
322
assert(user)(
323
hasField("id", _.id, isGreaterThan(0)) &&
324
hasField("name", _.name, isNonEmptyString) &&
325
hasField("email", _.email, matchesRegex(".*@.*".r))
326
)
327
```
328
329
## TestResult Type
330
331
Core type representing the outcome of test assertions.
332
333
```scala { .api }
334
/**
335
* Result of a test assertion
336
*/
337
trait TestResult {
338
/**
339
* True if the test succeeded
340
*/
341
def isSuccess: Boolean
342
343
/**
344
* True if the test failed
345
*/
346
def isFailure: Boolean
347
348
/**
349
* Add a custom message to this result
350
* @param message descriptive message
351
* @return test result with message
352
*/
353
def ??(message: String): TestResult
354
355
/**
356
* Combine with another test result using logical AND
357
*/
358
def &&(that: TestResult): TestResult
359
360
/**
361
* Combine with another test result using logical OR
362
*/
363
def ||(that: TestResult): TestResult
364
365
/**
366
* Negate this test result
367
*/
368
def unary_! : TestResult
369
}
370
371
object TestResult {
372
case class Succeeded(result: BoolAlgebra[AssertionValue]) extends TestResult
373
case class Failed(result: BoolAlgebra[AssertionValue]) extends TestResult
374
375
val succeed: TestResult
376
val fail: TestResult
377
}
378
```
379
380
## TestFailure and TestSuccess Types
381
382
```scala { .api }
383
/**
384
* Represents test failures with detailed information
385
*/
386
sealed trait TestFailure[+E] {
387
def map[E1](f: E => E1): TestFailure[E1]
388
}
389
390
object TestFailure {
391
case class Assertion(result: TestResult) extends TestFailure[Nothing]
392
case class Runtime[E](cause: Cause[E]) extends TestFailure[E]
393
}
394
395
/**
396
* Represents successful test completion
397
*/
398
case class TestSuccess() extends AnyVal
399
```