The documentation for ScalaTest is good, but I found that it lacked a little bit when it came to talking about custom matchers. As such, I thought it’d be useful to write up the approach I took recently when writing one.
Why use custom matchers?
My main motivation for using custom matchers was that they can make tests far more readable. At work, we deal with RDF a lot – and for a few reasons, we use a Java library to deal with it. Before using custom matchers, our tests had to jump through a few hoops:
That ended up being quite a lot to parse in one test – so it made sense to create a custom matcher.
For simplicity, I won’t carry on with the RDF example. Instead, we’ll write a custom matcher that checks the ending of a string. In your test, you can use a matcher like this:
Elsewhere, you then define your custom matcher as a
case class and use a
def to instantiate a new instance of it, like this:
There are a few key parts to what we just did:
- The constructor of the matcher. This takes the arguments passed to the ‘right’ of our custom matcher – in this case, the suffix. Since it’s a case class, we’ll have access to the suffix in our
applymethod This method performs our actual assertion. In this case, we’re using Scala’s built in
Stringobjects. Our checking needs to return a boolean, which is then wrapped up in a
MatchResultreturn value The
MatchResulttakes a boolean result, and two error messages. The first one is for when we expected the result to be
true, but it turned out to be
false. The second error message is used when the result was
true, but we expected it to be
false. This second case comes into play when we use a negated matcher (ie.
must not endWith).
- The method which instantiates our case class. Finally, so that we can use the word
endWithin our tests, we define a method which instantiates our
EndsWithMatcherwith the correct arguments.
And that’s pretty much all you need to know to be able to write your own custom matchers in ScalaTest, just like you’d do using rspec.