Skip to main content
Version: 2.0.x

How it Works?

note

In this section we are going to learn about the internals of the Assertion data type. So feel free to skip this section if you are not interested.

The test Function

In order to understand the Assertion data type, let's first look at the test function:

def test[In](label: String)(assertion: => In)(implicit testConstructor: TestConstructor[Nothing, In]): testConstructor.Out

Its signature is a bit complicated and uses path dependent types, but it doesn't matter. We can think of a test as a function from TestResult (or its effectful versions such as ZIO[R, E, TestResult] or ZSTM[R, E, TestResult]) to the Spec[R, E] data type:

def test(label: String)(assertion: => TestResult): Spec[Any, Nothing]
def test(label: String)(assertion: => ZIO[R, E, TestResult]): Spec[R, E]

Therefore, the function test needs a TestResult. The most common way to produce a TestResult is to resort to assert or its effectful counterpart assertZIO. The former one is for creating ordinary TestResult values and the latter one is for producing effectful TestResult values. Both of them accept a value of type A (effectful version wrapped in a ZIO) and an Assertion[A].

The assert Function

Let's look at the assert function:

def assert[A](expr: => A)(assertion: Assertion[A]): TestResult

It takes an expression of type A and an Assertion[A] and returns the TestResult which is the boolean algebra of the AssertionResult. Furthermore, we have an Assertion[A] which is capable of producing assertion results on any value of type A. So the assert function can apply the expression to the assertion and produce the TestResult.

The Assertion data type

We can think of an Assertion[A] as a function of type A => Boolean.

As a proposition, assertions compose using logical conjunction and disjunction and can be negated:

import zio.test._

val greaterThanZero: Assertion[Int] = Assertion.isPositive
val lessThanFive : Assertion[Int] = Assertion.isLessThan(5)
val equalTo10 : Assertion[Int] = Assertion.equalTo(10)

val assertion: Assertion[Int] = greaterThanZero && lessThanFive || equalTo10.negate

After composing them, we can run it on any expression:

import zio._

val result: TestResult = assertion.run(10)