Search code examples
scalaunit-testingspecs2monoidsscala-cats

Simple unit testing with monoids


Suppose I testing a function echo: String => String, which is just repeating the input, with specs2.

I can write a few tests like that:

class EchoSpec extends SpecificationWithJUnit {

  "echo should handle ASCII alphanumeric names" in {
    echo("abc") must beEqualTo("abc")
  }

  "echo should handle names with slashes" in {
     echo("a/b/c") must beEqualTo("a/b/c")
  }

  "echo should handle names with dots" in {
    echo("a.b.c") must beEqualTo("a.b.c")
  }

  "echo should handle non-ASCII names" in {
    echo("אבג") must beEqualTo("אבג")
  }
} 

However I would prefer to get rid of the boilerplate code. So I am using cats monoids:

import cats.implicits._

def testEcho(expected: String): String => Option[String] = {str =>
  if (str == expected) none else s"$str != expected".some
} 

def testEchoes(expected: List[String]): Option[String] = 
  expected foldMap testEcho map (_.mkString(", "))

"echo should handle all names" {
   val expected = List("abc", "a/b/c", "a.b.c", "אבג")
   testEcho(expected) must beNone
}

Does it make sense ? How to improve/simplify it ? Is the monoid is really necessary here ? Can I git rid of the boilerplate code from the above without monoid ?


Solution

  • List("abc", "a/b/c", "a.b.c", "אבג")
      .foreach(s => echo(s) must beEqualTo(s))