A few days ago I found out how easy it is to test Scalaz type class instances
with specs2 and ScalaCheck. It was impressive to see that it only required
a few additional lines of code in my test class to check that my monoid not only
has a `Monoid`

instance but that it actually satisfies the monoid laws.

In this post I want to show a minimal monoid example and what is needed for
testing the monoid laws. Let me briefly recap the monoid laws and why you want
to test them. As Wikipedia will tell you, a monoid is a set,
*S*, together with a binary operation "•" (called `append`

by Scalaz) that
satisfies the following three axioms:

Closure:For alla,binS, the result of the operationa•bis also inS.

Associativity:For alla,bandcinS, the equation (a•b) •c=a• (b•c) holds.

Identity element:There exists an elemente(called`zero`

by Scalaz) inS, such that for all elementsainS, the equatione•a=a•e=aholds.

In any implementation of `Monoid[S]`

only closure is guaranteed automatically by
the compiler because of the signature of `append`

(`def append(a: S, b: => S): S`

).
But if `append`

is really associative or if `zero`

is really the identity element
under `append`

is not guaranteed at all. To make sure that your `Monoid`

is
actually a monoid, you could either prove the laws for your current implementation
(and prove them again if you change the implementation) or you could test if those
laws hold for some random values. And this is where Scalaz, specs2, and
ScalaCheck play nicely together and make your law testing a lot easier!

Let's look at the example code. We start with the class for which we'll add a
`Monoid`

instance:

case class Vec(x: Int, y: Int)

`Vec`

is a simple container of two integers and our `Monoid[Vec]`

provides
componentwise addition:

import scalaz._ object Vec { implicit object VecMonoid extends Monoid[Vec] { def zero: Vec = Vec(0, 0) def append(v1: Vec, v2: => Vec): Vec = Vec(v1.x + v2.x, v1.y + v2.y) } implicit object VecEqual extends Equal[Vec] { def equal(v1: Vec, v2: Vec): Boolean = v1 == v2 } }

`Equal[Vec]`

, which can test two `Vec`

s for equality, is required for the law
testing.

The next step is to write the actual test code. ScalaCheck requires an
`implicit Arbitrary[Vec]`

in order to generate random `Vec`

values. Once
we have that, we ask scalaz-specs2 to check all monoid laws for `Vec`

in one line of code (and while we are at it, we also check the equal laws):

import org.scalacheck.Arbitrary import org.specs2.scalaz._ import scalaz.scalacheck.ScalazProperties._ class VecSpec extends Spec { implicit val arbitraryVec = Arbitrary { for { (x, y) <- Arbitrary.arbitrary[(Int, Int)] } yield Vec(x, y) } checkAll(monoid.laws[Vec]) checkAll(equal.laws[Vec]) }

Et voilà! That is all it takes to test the laws for `Monoid[Vec]`

.
Simple, isn't it? If we run `VecSpec`

, we'll get the following output:

VecSpec monoid must satisfy + monoid.semigroup.associative + monoid.left identity + monoid.right identity equal must satisfy + equal.commutativity + equal.reflexive + equal.transitive + equal.naturality Total for specification VecSpec Finished in 20 ms 7 examples, 700 expectations, 0 failure, 0 error

For each law 100 tests with random `Vec`

values are performed and all passed
without any error. Now we are a lot more confident that our `Monoid[Vec]`

is
actually a monoid.

The complete example with a sbt build file is on GitHub
(scalaz-monoid-example). Just clone it and run `sbt test`

to see the
law testing in action.