Skip to main content
Version: 2.x

Test Hierarchies and Organization

A Spec[R, E] is the backbone of ZIO Test. All specs require an environment of type R and may potentially fail with an error of type E.

We can think of a spec as just a collection of tests. It is essentially a recursive data structure where every spec is just one individual test or a suite that itself can have multiple specs inside that each could be tests or sub suites. We can go down as far as we want in a recursive tree-like data structure.

A Single Spec

The test constructor creates one single spec:

import zio.test._

val mySpec = test("true is true") {
assertTrue(true)
}

Real tests that run some logic and return testing result are created mostly with test function. It expects two arguments, first one will be the label of test which will be used for visual reporting back to the user, and an assertion which contains some testable logic specified about a target under the test.

Collection of Multiple Specs

The suite creates a suite which contains other specs (tests or suites):

import zio.test._

val mySuite =
suite("A suite containing multiple tests")(
test("the first test") {
assertTrue(1 + 1 == 2)
},
test("the second test") {
assertTrue(2 * 2 == 4)
}
)

Suites can contain other suites. We can have multiple suites and one big suite that will aggregate them all:

import zio.test._

suite("int and string")(
suite("int suite")(
test("minus")(assertTrue(2 - 1 == 1)),
test("plus")(assertTrue(1 + 1 == 2))
),
suite("string suite")(
test("concat")(assertTrue("a" + "b" == "ab")),
test("length")(assertTrue("abc".length == 3))
)
)

Collection of Multiple Smart Specs

The suite method creates a spec from a collection of specs. So what we can do is to provide it with a collection of specs:

import zio.test._

object ExampleSpec extends ZIOSpecDefault {

def spec =
suite("some suite")(
test("test 1") {
val stuff = 1
assertTrue(stuff == 1)
},
test("test 2") {
val stuff = Some(1)
assertTrue(stuff == Some(1))
}
)

}

But what if we wanted to have a suite of tests that work on a common value, e.g. the same stuff? ZIO provides the suiteAll method that helps us to share the same stuff between all tests:

import zio.test._

object ExampleSpec extends ZIOSpecDefault {

def spec =
suiteAll("some suite") {

val stuff = "hello"

test("test 1") {
assertTrue(stuff.startsWith("h"))
}

val stuff2 = 5

test("test 2") {
assertTrue(stuff.length == stuff2)
}
}

}

Sharing the result of an effectful value between tests

As we saw in the previous section, the suiteAll method allows tests to work with common values. But what if the value is a result of some effect and we want to use it in several tests, without running the effect every time? Suites in zio-test can be effectual, so we can use this feature to share effectual values:

import zio._
import zio.test._

object ExampleSpec extends ZIOSpecDefault {
val spec =
suite("some suite") {
for {
stuff <- ZIO.succeed("hello")
stuff2 = 5
} yield Chunk(

test("test 1") {
assertTrue(stuff.startsWith("h"))
},

test("test 2") {
assertTrue(stuff.length == stuff2)
}

)
}
}