Scala 06 Oct 2008 09:15 pm
Testing Scala using specs
As I mentioned in an earlier post, Scala offers many alternatives for unit testing. With its Java interoperability using JUnit or TestNg is no more difficult than using the purpose built testing frameworks for Scala such as ScalaTest, Rehersal, specs, and ScalaCheck.
My personal favourite is specs. The specs testing framework, is a Behaviour-Driven-Design testing tool written in Scala by Eric Torreborre.
Below is a very simple example of a specs test.
package com.gigantiq.thing
import org.specs._
object ThingSpecification extends Specification {
”A Thing” should {
”have a name equal to the passed value” in {
val thing = new Thing(”myThing”)
thing.name mustMatch “myThing”
}
”throw an IllegalArgumentException if passed a blank name” in {
new Thing(”") must throwA(new IllegalArgumentException)
}
}
}
The import org.specs._ statement is importing everything from the import org.specs package. The _ is equivalent to * in a java import statement.
Next we declare a specification with the following syntax…
object ThingSpecification extends Specification {
…
}
They object key word in Scala declares a singleton object. So in this case we have declared a singleton called ThingSpecification that extends the abstract class called Specification as provided by the specs library.
The specs library utilizes Scala’s flexibility to define a DSL that allows us to construct a very human readable specification.
"A Thing" should {
”have a name equal to the passed value” in {
val thing = new Thing(”myThing”)
thing.name mustMatch “myThing”
}
”throw an IllegalArgumentException if passed a blank name” in {
new Thing(”") must throwA(new IllegalArgumentException)
}
}
Looking at this example we can see clearly that we are expecting the following behavior from our application that we are writing.
- A Thing should have a name equal to the passed value.
- A Thing should throw an IllegalArgumentException if passed a blank name.
Before we can run this Specification we need the Thing class otherwise our tests will fail. So in the conciseness of Scala, here it is:
package com.gigantiq.thing
class Thing(val name: String) {
require(name.length > 0)
}
We can now compile our application. Once we have done that we can run our specification using the scala command.
andytrigg$ scala -cp specs-1.3.1.jar com.gigantiq.thing.ThingSpecification
Upon execution of this specification we receive the following output to our console.
Specification "ThingSpecification"
A Thing should
+ have a name equal to the passed value
+ throw an IllegalArgumentException if passed a blank name
Total for specification “ThingSpecification”:
Finished in 0 second, 49 ms
2 examples, 2 assertions, 0 failure, 0 error
Just for completeness I would like to show what happens in the event of a test failing. If we remove the precondition check(require(name.length > 0)) from our Thing class and rerun our specification, we will get the following output.
Specification "ThingSpecification"
A Thing should
+ have a name equal to the passed value
x throw an IllegalArgumentException if passed a blank name
java.lang.IllegalArgumentException should have been thrown (ThingSpecification.scala:12)
Total for specification “ThingSpecification”:
Finished in 0 second, 49 ms
2 examples, 2 assertions, 1 failure, 0 error
In the above examples I illustrated the use of two of the matchers that specs offers out of the box. Matchers are used for specifying the assertion being made in the specifications. The ones we have used here are:
mustMatch: used for asserting matching stringsmust throwA: used to evaluate that an expected exception is thrownIn addition to these, specs offers many matchers and it is very easy to write your own if none of the standard matchers suffice.
As you can see, unit testing doesn’t get much simpler than that. I love those specs.

