Effective assertions, from Java to Scala
Unit testing should be part of any project. Hard to disagree. However, many complementary tools exist for various purposes. This is the case for assertions, which allow to verify the expected behavior of the system. Different tools have different strengths and weaknesses. Starting within the Java world with JUnit, Hamcrest, FEST-Assert and AssertJ, this high level review will end in the Scala world with ScalaTest and Specs2.
JUnit Assert, the first stop
Junit is the most widely used unit testing library for java. Of course, it comes with its own solution for assertions.
The assertions are static methods following the same signature pattern assertXXX([optionalMessage],expected,actual).
A typical example would be :
That’s a good start. Most people will stop here. Indeed, why bother searching for an alternative if the default solution is sufficient? But let’s continue.
Hamcrest, to the rescue?
One issue with JUnit standard assertions is their stiffness. They work perfectly for their exact use case but as soon as a more complex test needs to be written, it is the responsability of the developer to write the additional, boilerplate, code. Hamcrest is a set of matchers created to solve this issue. It is now possible to compose the assertions. JUnit is nowadays bundled with the core of Hamcrest.
The basics are aven simpler : there is a single assert,
but with powerfull flexibility.
Of course, this example is contrieved. But what would be the same with JUnit Assert? More complicated, yes. For those interested, Ed Gibbs wrote a good walkthrough on Hamcrest.
FEST-Assert, the late solution
People may argue that Hamcrest matchers help readability. It may be true with regard to JUnit but not in general. One issue with Hamcrest is that efficient nesting of matchers requires a good knowledge of existing matchers. The Assertions from the FEST project are an alternative solution alleviating this issue by casting the Java type system as a tutor for the developer.
Thanks to the Java type system and IDE autocompletion, the relevant assertions will be shown during the chaining. Learning becomes easier and so does reading. Indeed, the
hasSize will only be available for
Collection and the chaining removes all the parentheses noise that would have been created by Hamcrest.
Sadly, the project died during its attempt to improve itself with a second version. The lastest stable release is from 2011.
AssertJ, the new old
FEST-Assert is dead but… actually was forked and is still alive under a new name : AssertJ. The principle has not changed but additional features have appeared. Among those, the soft assertions should be checked out! In short, even if 10s assertions are written sequentially, on failure, the error message will contain all differences and not only the first one.
For new Java projects, I would definitely pick AssertJ over JUnit Assert, Hamcrest or FEST-Assert.
ScalaTest, for Scala
ScalaTest is one of the most widely used test framework for Scala. It “does not try to impose a testing philosophy on you” but supports indeed many ways of expressing a test. Of course, it also includes its own Matchers.
Here are a few examples.
Thanks to a different language, the readability is improved again, even though a few technical artefacts are still left (eg
shouldBe). The syntactic sugar allows to remove parentheses, points and semi-colons. Here are the same examples, sugar free.
The principle is quite close to how Hamcrest works. The main difference is the root assertion (
should) being applied to the observed data instead of being a static method. That’s another Scala feature, ie implicit conversions. The
result is transparently converted to another type owning the
shouldBe methods. It’s the so-called ‘pimp my library’ pattern.
AssertJ fast learning curve is an asset. Should AssertJ used for a project moving from Java to Scala? Well, its lack of native support for Scala types is not in its favor. ScalaTest assertions do not seem to be the most attractive part of Scala for a well advised Java developer.
Are you a Java developer switching to Scala? Are you a Scala developer coaching Java developer? Have you been on a project migrating from Java to Scala? What are your assertions about assertions?