Friday, March 10, 2017

Some mistakes to avoid when using Scalatest

I've been writing a lot of Scalatest specifications lately. And I've discovered a couple of tips which I think are worth sharing.

First, it's a common pattern, especially if you are doing anything like parsing, that you want to do something like this:


val expr = "x>1 & (x<3 | x=99)""rule" should s"parse $expr using parseRule" in {
  val parser = new RuleParser()
  parser.parseRule(expr) should matchPattern { case scala.util.Success(_) => }
}
Unfortunately, there's a snag. If you want to repeat that specific test (and not the remainder of the Specification), it will result in a run that is green (!) but which contains the message "Empty test suite". That seems like a bug in the test runner to me--it shouldn't show green when it didn't actually test anything. But there's an easy workaround for this that will allow you to repeat that specific test. Just write it like this:

val expr = "x>1 & (x<3 | x=99)""rule" should "parse " + expr + " using parseRule" in {
  val parser = new RuleParser()
  parser.parseRule(expr) should matchPattern { case scala.util.Success(_) => }
}

It's very slightly more awkward to write the code but it's not that hard, especially if you know the trick to splitting a String. Just be sure to avoid using s"...".The second problem I ran into is a little more troubling.


behavior of "silly"
it should "use for comprehension properly" in {
  for (x <- Try("x")) yield x=="y" should matchPattern { case Success(true) => }
}
The result of running this was green:
Testing started at 11:06 AM ...


Process finished with exit code 0

See anything wrong? Clearly, the result should have been Success(false) but it apparently matched. Or did it? Actually, it the whole expression of yield through } was run as a side effect, yielding nothing. And, although I haven't really gone into detail, clearly the test runner didn't get any message about a failure. I don't think this is a bug, although it might perhaps be possible to fix it. But all you have to do is to ensure that you put parentheses around the entire for comprehension thus:
(for (x <- Try("x")) yield x=="y") should matchPattern { case Success(true) => }

No comments:

Post a Comment