Skip to content

Commit

Permalink
Rework some Testing examples. #bill #time 30m
Browse files Browse the repository at this point in the history
Distinguish between "tests" and "effects that end with assertions" in our variable names.

Go further with `val`s. Prose around test generation
  • Loading branch information
swoogles committed Jul 20, 2024
1 parent 23a34d0 commit 824032a
Showing 1 changed file with 53 additions and 18 deletions.
71 changes: 53 additions & 18 deletions Chapters/05_Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,32 @@ import zio.test.*
def spec =
test("Effect as test"):
defer:
printLine("This Effect is a test").run
printLine("Running Effect in a test")
.run
assertCompletes
```

The `defer` produces an Effect that runs the `printLine` and returns `assertCompletes`.
`assertCompletes` unconditionally indicates that everything ran successfully.

We can assign the Effect to a `val` and use that as the test:
```scala 3 mdoc:silent
import zio.test.*

// TODO Better name for this function
def testLogic(label: String) =
defer:
printLine(s"Running $label").run
assertCompletes
```

We can assign the Effect to a `val` and use that as the test logic:

```scala 3 mdoc:silent testzio
import zio.*
import zio.direct.*
import zio.test.*

val aTest =
defer:
printLine("This is aTest").run
assertCompletes
val effectA = testLogic("A")
```

```scala 3 mdoc:testzio
Expand All @@ -113,8 +121,8 @@ import zio.direct.*
import zio.test.*

def spec =
test("aTest"):
aTest
test("case A"):
effectA
```

Tests are typically collected into a `suite`.
Expand All @@ -125,22 +133,49 @@ import zio.*
import zio.direct.*
import zio.test.*

val bTest =
defer:
printLine("This is bTest").run
assertTrue(1 == 1)
val effectB = testLogic("B")

def spec =
suite("A Suite of Tests")(
test("aTest in Suite"):
aTest
suite("Suite of Tests")(
test("case A in Suite"):
effectA
,
test("bTest in Suite"):
bTest,
test("case A in Suite"):
effectB,
)
```

Tests run in parallel so the output does not necessarily appear in the order the tests are listed.
Tests run in parallel by default so the output does not necessarily appear in the order the tests are listed.

Going further with our values, we can store complete test cases in `val`s:

```scala 3 mdoc:silent
def testCase(label: String) =
test(s"case $label in a value"):
testLogic(label)
```

```scala 3 mdoc:silent
val testA = testCase("A")
val testB = testCase("B")
```

```scala 3 mdoc:testzio
import zio.*
import zio.direct.*
import zio.test.*

def spec =
suite("A Suite of Tests")(testA, testB)
```

This flexibility is very empowering.
Traditionally, you have to compromise between concise tests and the clarity of the test output.
Do you want to write 1 test with 100 assertions, or 100 tests with 1 assertion each?
The first is concise and quick to write but failures are difficult to read.
The second is very clear about what failed, but requires writing a lot of boilerplate.

With an Effect Oriented test library, it is possible to generate tests programmatically, getting the best of both worlds.

## Birdhouse Factory

Expand Down

0 comments on commit 824032a

Please sign in to comment.