views:

208

answers:

1

There are some nice libraries for testing in Scala (Specs, ScalaTest, ScalaCheck). However, with Scala's powerful type system, important parts of an API being developed in Scala are expressed statically, usually in the form of some undesirable or disallowed behavior being prevented by the compiler.

So, what is the best way to test whether something is prevented by the compiler when designing an library or other API? It is unsatisfying to comment out code that is supposed to be uncompilable and then uncomment it to verify.

A contrived example testing List:

val list: List[Int] = List(1, 2, 3)
// should not compile
// list.add("Chicka-Chicka-Boom-Boom")

Does one of the existing testing libraries handle cases like this? Is there an approach that people use that works?

The approach I was considering was to embed code in a triple-quote string or an xml element and call the compiler in my test. Calling code looking something like this:

should {
  notCompile(<code>
    val list: List[Int] = List(1, 2, 3)
    list.add("Chicka-Chicka-Boom-Boom")
  </code>)
}

Or, something along the lines of an expect-type script called on the interpreter.

+6  A: 

Hi Mitch,

I have created some specs executing some code snippets and checking the results of the interpreter.

You can have a look at the Snippets trait. The idea is to store in some org.specs.util.Property[Snippet] the code to execute:

val it: Property[Snippet] = Property(Snippet(""))
"import scala.collection.List" prelude it // will be prepended to any code in the it snippet
"val list: List[Int] = List(1, 2, 3)" snip it // snip some code (keeping the prelude)
"list.add("Chicka-Chicka-Boom-Boom")" add it  // add some code to the previously snipped code. A new snip would remove the previous code (except the prelude)

 execute(it) must include("error: value add is not a member of List[Int]") // check the interpreter output

The main drawback I found with this approach was the slowness of the interpreter. I don't know yet how this could be sped up.

Eric.

Eric
That's a little slice of awesome. Thanks for reading my mind!
Mitch Blevins