# Law testing

Laws are an important part of cats.
Cats uses `catalysts`

and `discipline`

to help test instances with laws.
To make things easier, cats ships with `cats-testkit`

, which makes use of `catalysts`

and `discipline`

and exposes `CatsSuite`

based on ScalaTest.

## Getting started

First up, you will need to specify dependencies on `cats-laws`

and `cats-testkit`

in your `build.sbt`

file.
To make things easier, we’ll also include the `scalacheck-shapeless`

library in this tutorial, so we don’t have to manually write instances for ScalaCheck’s `Arbitrary`

.

```
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-laws" % "1.0.1" % Test,
"org.typelevel" %% "cats-testkit" % "1.0.1"% Test,
"com.github.alexarchambault" %% "scalacheck-shapeless_1.13" % "1.1.6" % Test
)
```

## Example: Testing a Functor instance

We’ll begin by creating a data type and its Functor instance.

```
import cats._
// import cats._
sealed trait Tree[+A]
// defined trait Tree
case object Leaf extends Tree[Nothing]
// defined object Leaf
case class Node[A](p: A, left: Tree[A], right: Tree[A]) extends Tree[A]
// defined class Node
object Tree {
implicit val functorTree: Functor[Tree] = new Functor[Tree] {
def map[A, B](tree: Tree[A])(f: A => B) = tree match {
case Leaf => Leaf
case Node(p, left, right) => Node(f(p), map(left)(f), map(right)(f))
}
}
}
// defined object Tree
// warning: previously defined trait Tree is not a companion to object Tree.
// Companions must be defined together; you may wish to use :paste mode for this.
```

We will also need to create an `Eq`

instance, as most laws will need to compare values of a type to properly test for correctness.
For simplicity we’ll just use `Eq.fromUniversalEquals`

:

```
implicit def eqTree[A: Eq]: Eq[Tree[A]] = Eq.fromUniversalEquals
// eqTree: [A](implicit evidence$1: cats.Eq[A])cats.Eq[Tree[A]]
```

Then we can begin to write our law tests. Start by creating a new class in your `test`

folder and inheriting from `cats.tests.CatsSuite`

.
`CatsSuite`

extends the standard ScalaTest `FunSuite`

as well as `Matchers`

.
Furthermore it also pulls in all of cats instances and syntax, so there’s no need to import from `cats.implicits._`

.

```
import cats.tests.CatsSuite
// import cats.tests.CatsSuite
class TreeLawTests extends CatsSuite {
}
// defined class TreeLawTests
```

The key to testing laws is the `checkAll`

function, which takes a name for your test and a Discipline ruleset.
Cats has defined rulesets for all type class laws in `cats.laws.discipline.*`

.

So for our example we will want to import `cats.laws.discipline.FunctorTests`

and call `checkAll`

with it.
Before we do so, however,
we will have to bring our instances into scope as well as the derived `Arbitrary`

instances from `scalacheck-shapeless`

(We have defined an Arbitrary instance for `Tree`

here, but you won’t need it if you import `org.scalacheck.ScalacheckShapeless._`

).

```
import org.scalacheck.{Arbitrary, Gen}
implicit def arbFoo[A: Arbitrary]: Arbitrary[Tree[A]] =
Arbitrary(Gen.oneOf(Gen.const(Leaf), (for {
e <- Arbitrary.arbitrary[A]
} yield Node(e, Leaf, Leaf)))
)
```

```
import Tree._
// import Tree._
import cats.laws.discipline.FunctorTests
// import cats.laws.discipline.FunctorTests
class TreeLawTests extends CatsSuite {
checkAll("Tree.FunctorLaws", FunctorTests[Tree].functor[Int, Int, String])
}
// defined class TreeLawTests
```

Now when we run `test`

in our sbt console, ScalaCheck will test if the `Functor`

laws hold for our `Tree`

type.
You should see something like this:

```
[info] TreeLawTests:
[info] - Tree.FunctorLaws.functor.covariant composition
[info] - Tree.FunctorLaws.functor.covariant identity
[info] - Tree.FunctorLaws.functor.invariant composition
[info] - Tree.FunctorLaws.functor.invariant identity
[info] ScalaTest
[info] Run completed in 537 milliseconds.
[info] Total number of tests run: 4
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 4, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[info] Passed: Total 4, Failed 0, Errors 0, Passed 4
[success] Total time: 1 s, completed Aug 31, 2017 2:19:22 PM
```

And voila, you’ve successfully proven that your data type upholds the Functor laws!

### Testing cats.kernel instances

For most of the type classes included in cats, the above will work great.
However, the law tests for the type classes inside `cats.kernel`

are located in `cats.kernel.laws.discipline.*`

instead.
So we have to import from there to test type classes like `Semigroup`

, `Monoid`

, `Group`

or `Semilattice`

.

Let’s test it out, by defining a `Semigroup`

instance for our `Tree`

type.

```
import cats.implicits._
// import cats.implicits._
implicit def semigroupTree[A: Semigroup]: Semigroup[Tree[A]] = new Semigroup[Tree[A]] {
def combine(x: Tree[A], y: Tree[A]) = (x, y) match {
case (Leaf, _) => Leaf
case (_, Leaf) => Leaf
case (Node(xp, xLeft, xRight), Node(yp, yLeft, yRight)) =>
Node(xp |+| yp, xLeft |+| yLeft, xRight |+| yRight)
}
}
// semigroupTree: [A](implicit evidence$1: cats.Semigroup[A])cats.Semigroup[Tree[A]]
```

Then we can again test the instance inside our class extending `CatsSuite`

:

```
import cats.laws.discipline.FunctorTests
// import cats.laws.discipline.FunctorTests
import cats.kernel.laws.discipline.SemigroupTests
// import cats.kernel.laws.discipline.SemigroupTests
class TreeLawTests extends CatsSuite {
checkAll("Tree[Int].SemigroupLaws", SemigroupTests[Tree[Int]].semigroup)
checkAll("Tree.FunctorLaws", FunctorTests[Tree].functor[Int, Int, String])
}
// defined class TreeLawTests
```