Skip to content

Commit

Permalink
Changed Material/Tools example to compact form #bruce #time 30m
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruce Eckel committed Jul 22, 2024
1 parent 56fa76b commit 7351731
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 86 deletions.
47 changes: 14 additions & 33 deletions Chapters/05_Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,58 +182,39 @@ An Effect Oriented test library produces the best of both worlds by generating t
## Birdhouse Factory

Suppose you want to build birdhouses as fast as possible, and you have a choice of materials for building them.
The `Material`s have different levels of `brittleness` so some `Tool`s might break some `Material`s.
We want to test different `Material`s with different combinations of `Tool`s.
All `Material`s and `Tool`s have `ZLayer` services, so we easily swap them around during testing.
The `Material`s have different levels of `brittleness` so some tools might break some `Material`s.
We want to test different `Material`s with different combinations of tools.
All `Material`s and tools have `ZLayer` services, so we easily swap them around during testing.

`Wood` and `Plastic` are `Material`s with different `brittleness` factors:

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

trait Material:
val brittleness: Int

case class Wood() extends Material:
val brittleness = 5

case class Plastic() extends Material:
val brittleness = 10
class Material(val brittleness: Int)

object Material:
val wood = ZLayer.succeed(Wood())
val plastic = ZLayer.succeed(Plastic())
val wood = ZLayer.succeed(Material(brittleness = 5))
val plastic = ZLayer.succeed(Material(brittleness = 10))
```

We define `Tool`s in a similar way.
Each type of `Tool` has an `intensity` that relates it to `Material.brittleness`.
Different types of `Saw` and `Nailer` each have an `intensity` that relates it to `Material.brittleness`.

```scala 3 mdoc:silent testzio
import zio.*
import zio.Console.*

trait Tool:
val intensity: Int

trait Saw extends Tool
case class HandSaw() extends Saw:
val intensity = 4
case class RoboSaw() extends Saw:
val intensity = 8
class Saw(val intensity: Int)

object Saw:
val hand = ZLayer.succeed(HandSaw())
val robotic = ZLayer.succeed(RoboSaw())
val hand = ZLayer.succeed(Saw(intensity = 4))
val robotic = ZLayer.succeed(Saw(intensity = 8))

trait Nailer extends Tool
case class Hammer() extends Nailer:
val intensity = 4
case class RoboNailer() extends Nailer:
val intensity = 11
class Nailer(val intensity: Int)

object Nailer:
val hand = ZLayer.succeed(Hammer())
val robotic = ZLayer.succeed(RoboNailer())
val hand = ZLayer.succeed(Nailer(intensity = 4))
val robotic = ZLayer.succeed(Nailer(intensity = 11))
````

The test takes a `Material` and checks it against a `Saw` and a `Nailer`:
Expand Down Expand Up @@ -297,7 +278,7 @@ It gives all the information you need to see exactly what's happening.

We've only shown a few combinations here.
As an exercise, try adding others.
Then add a new `Material` called `Metal`, and a new `Tool` category called `Power`, with an additional type `Drill`.
Then add a new `Material` called `Metal`, and a new tool category called `Power`, with an additional type `Drill`.

## Testing Effects

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package birdhouse
package basic

import zio.*
import zio.direct.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,68 +1,27 @@
package birdhouse
package experiments

import zio.*

trait Material:
val brittleness: Int

case class Wood() extends Material:
val brittleness = 5

case class Plastic() extends Material:
val brittleness = 10
class Material(val brittleness: Int)

object Material:
val wood = ZLayer.succeed(Wood())
val plastic = ZLayer.succeed(Plastic())

import zio.Console.*

trait Tool:
val action: String
val intensity: Int
val use =
printLine(
s"$this $action, intensity $intensity"
)
val wood = ZLayer.succeed(Material(brittleness = 5))
val plastic = ZLayer.succeed(Material(brittleness = 10))

trait Saw extends Tool:
val action = "sawing"
case class HandSaw() extends Saw:
val intensity = 4
case class RoboSaw() extends Saw:
val intensity = 8
class Saw(val intensity: Int)

object Saw:
val hand = ZLayer.succeed(HandSaw())
val robotic = ZLayer.succeed(RoboSaw())
val hand = ZLayer.succeed(Saw(intensity = 4))
val robotic = ZLayer.succeed(Saw(intensity = 8))

trait Nailer extends Tool:
val action = "nailing"
case class Hammer() extends Nailer:
val intensity = 4
case class RoboNailer() extends Nailer:
val intensity = 11
class Nailer(val intensity: Int)

object Nailer:
val hand = ZLayer.succeed(Hammer())
val robotic = ZLayer.succeed(RoboNailer())

// Just checking

import zio.direct.*

object UseTools extends ZIOAppDefault:
def run =
defer:
List(
Hammer(),
RoboNailer(),
HandSaw(),
RoboSaw(),
).foreach(_.use.run)
// end checking
val hand = ZLayer.succeed(Nailer(intensity = 4))
val robotic = ZLayer.succeed(Nailer(intensity = 11))

import zio.test.*
import zio.direct.*

val testToolWithMaterial =
defer:
Expand Down

0 comments on commit 7351731

Please sign in to comment.