Once I managed to get hello world working (see Getting Started With Scala) I wanted to find out how to write a simple test. A friend recommended specs2 so that is what I'm going with.

Create a build definition

Following this guide I created a build.sbt file in my projects root

mark@sister:~/src/scala/hello$ ls -la
total 24
drwxr-xr-x 4 mark mark 4096 Nov  6 07:49 .
drwxr-xr-x 6 mark mark 4096 Nov  4 07:56 ..
-rw-r--r-- 1 mark mark   65 Nov  6 07:49 build.sbt
-rw-r--r-- 1 mark mark   78 Nov  4 08:04 helloWorld.scala
drwxr-xr-x 3 mark mark 4096 Nov  6 07:46 project
drwxr-xr-x 5 mark mark 4096 Nov  4 08:07 target
mark@sister:~/src/scala/hello$ 

In the .sbt file, the blank lines are significant*, see the scala-sbt docs, so my initial file looks like this:

* apparently no longer significant with recent versions of sbt ymmv

name := "hello mark"

version := "1.0"

scalaVersion := "2.10.5"

Testing that this file is valid I run

sbt run
mark@sister:~/src/scala/hello$ sbt run
[info] Set current project to hello mark (in build file:/home/mark/src/scala/hello/)
[info] Running HelloWorld 
Hello World!
[success] Total time: 1 s, completed 06-Nov-2015 07:56:12
mark@sister:~/src/scala/hello$ 

Note the subtle change in the name, now reported as hello mark

Now to add a test

Yes I know, the tests should have come first, but not testing is simpler and I always like to start with the simplest task first.

Following Eric Torreborre's Quickstart I added the following to my build.sbt:

libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")

scalacOptions in Test ++= Seq("-Yrangepos")

and I created a new file HelloWorldSpec.scala

mark@sister:~/src/scala/hello$ cat HelloWorldSpec.scala

import org.specs2_
class HelloWorldSpec extends Specification { def is = s2"""

This is my first specification
  it is working                 $ok
  really working!               $ok
                                """
}

I then ran sbt compile

[info] Set current project to hello mark (in build file:/home/mark/src/scala/hello/)
[info] Compiling 1 Scala source to /home/mark/src/scala/hello/target/scala-2.10/classes...
[error] /home/mark/src/scala/hello/HelloWorldSpec.scala:1: object specs2_ is not a member of package org
[error] import org.specs2_
[error]        ^
[error] /home/mark/src/scala/hello/HelloWorldSpec.scala:2: not found: type Specification
[error] class HelloWorldSpec extends Specification { def is = s2"""
[error]                              ^
[error] /home/mark/src/scala/hello/HelloWorldSpec.scala:2: value s2 is not a member of StringContext
[error] class HelloWorldSpec extends Specification { def is = s2"""
[error]                                                       ^
[error] three errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 1 s, completed 07-Nov-2015 08:30:23

Ok so that didn't work. It appears that the compiler isn't finding org.specs2!

So here's my file layout, note that project and target directories have been created by the build tool.

mark@sister:~/src/scala/hello$ ls -la
total 28
drwxr-xr-x 4 mark mark 4096 Nov  7 08:34 .
drwxr-xr-x 6 mark mark 4096 Nov  4 07:56 ..
-rw-r--r-- 1 mark mark  185 Nov  7 08:33 build.sbt
-rw-r--r-- 1 mark mark   78 Nov  6 08:15 HelloWorld.scala
-rw-r--r-- 1 mark mark  229 Nov  6 08:11 HelloWorldSpec.scala
drwxr-xr-x 3 mark mark 4096 Nov  7 08:33 project
drwxr-xr-x 5 mark mark 4096 Nov  7 08:34 target

My build layout is non-statndard so I set up a structure as suggested on the sbt man pages

mark@sister:~/src/scala/hello$ mkdir -p src/main/scala
mark@sister:~/src/scala/hello$ mkdir -p src/test/scala
mark@sister:~/src/scala/hello$ mv HelloWorld.scala src/main/scala/
mark@sister:~/src/scala/hello$ mv HelloWorldSpec.scala src/test/scala/
mark@sister:~/src/scala/hello$ sbt clean
mark@sister:~/src/scala/hello$ sbt compile

This now works fine for compilation

[info] Set current project to hello (in build file:/home/mark/src/scala/hello/)
[info] Updating {file:/home/mark/src/scala/hello/}hello...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /home/mark/src/scala/hello/target/scala-2.10/classes...
[success] Total time: 3 s, completed 07-Nov-2015 08:39:02

but running sbt test still causes the same compile error, so it wasn't my directory structure.

mark@sister:~/src/scala/hello$ sbt test
[info] Set current project to hello (in build file:/home/mark/src/scala/hello/)
[info] Compiling 1 Scala source to /home/mark/src/scala/hello/target/scala-2.10/test-classes...
[error] /home/mark/src/scala/hello/src/test/scala/HelloWorldSpec.scala:1: object specs2_ is not a member of package org
[error] import org.specs2_
[error]        ^
[error] /home/mark/src/scala/hello/src/test/scala/HelloWorldSpec.scala:2: not found: type Specification
[error] class HelloWorldSpec extends Specification { def is = s2"""
[error]                              ^
[error] /home/mark/src/scala/hello/src/test/scala/HelloWorldSpec.scala:2: value s2 is not a member of StringContext
[error] class HelloWorldSpec extends Specification { def is = s2"""
[error]                                                       ^
[error] three errors found
[error] (test:compileIncremental) Compilation failed
[error] Total time: 2 s, completed 07-Nov-2015 08:41:51
mark@sister:~/src/scala/hello$ sbt compile

Maybe time to stop guessing and try a bit of research... watch this space

After a bit of hackery and some trial and error, it appears that the solution is to import the Specification class explicitly, replacing import org.specs2 with import.specs2.Specification. This resulted in success.

mark@sister:~/src/scala/hello$ git diff src/test/scala/HelloWorldSpec.scala
--- a/src/test/scala/HelloWorldSpec.scala
+++ b/src/test/scala/HelloWorldSpec.scala
-import org.specs2_
+import org.specs2.Specification

mark@sister:~/src/scala/hello$ sbt test
[info] Loading project definition from /home/mark/src/scala/hello/project
[info] Set current project to hello (in build file:/home/mark/src/scala/hello/)
[info] Updating {file:/home/mark/src/scala/hello/}hello...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] HelloWorldSpec
[info] 
[info]   This is my first specification
[info]     + it is working
[info]     + really working!
[info] 
[info] Total for specification HelloWorldSpec
[info] Finished in 26 ms
[info] 2 examples, 0 failure, 0 error
[info] 
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 2 s, completed 07-Nov-2015 09:51:29

Great, so we have a scala app that runs and a test that asserts that true is true. It's a start I suppose, nothing wrong with baby steps.