packages

Tdd

A good idea for a project that is large or going to get large fast is to use Test Driven Development. I am a practitioner of this methodology and have seen its benefits many times in my career. To get going in Scala here are the steps I followed.

Installation & Setup

SBT

First you are going to need SBT. I used brew on my mac to get it, you can follow the install notes on the link for SBT if you are on another platform.

ScalaTest

Then, you are going to need to get Scala Test it seems like the “go to” testing framework in the Scala ecosystem. Check this installation guide out. I followed the setup for SBT.

If you have a project and it is not an SBT Scala project you will need to either import the project to use SBT or start a new SBT project. Depending on your tooling and IDE this might happen in one shot (and gracefully) or you will need to go heads down in config hell for a while to make everything work. Check docs and links for your specific tools (eclipse, etc) to get this working.

I used IntelliJ without SBT initially. After trying a few different things. I decided to create a new SBT project in IntelliJ and move my project src files into the new project.

Once I had my intelliJ project wired up, I had to run the build.sbt file and grab the new dependencies. After a fair amount of trial and error and researching versions and paths, the working sbt build file looked like:

name := "project"
version := "1.0"
scalaVersion := "2.12.1"
libraryDependencies ++=Seq(
  "org.scalactic" %% "scalactic" % "3.0.1",
  "org.scalatest" %% "scalatest" % "3.0.1" % "test" ,
  "org.scala-lang.modules" % "scala-xml_2.12" % "1.0.6",
  "org.scala-lang" % "scala-reflect" % "2.12.1"
)

Given you have no more SBT errors you should be set as far as installation and setup goes.

SBT expects tests and source to be in different directories in your project. Per the docs I setup mine up like:

Directory Structure

└── /src
  └── /main
    └── /scala
      └── thing.scala


└── /src
  └── /test
      └──/scala
          └──thing_test.scala

Code

Put in the test and ensure it fails, for my toy example I am only going to make sure that method under test returns a string.

//thing_test.scala
import org.scalatest.FunSpec
class ThingTests extends FunSpec{
  describe("object responds") {
    it("will respond") {
      val thing = new Thing("Franky")
      assert(thing.speak == "I am Franky")
    }
  }
}

Note I am importing FunSpec because it is close to Rspec the Ruby testing Framework I am used to.

Run the test and enjoy all the errors that are displayed. You can run tests with sbt test from the project root folder.

Since we have not written any code yet:

Write the tests first and fail them out before writing the production code

You should see errors like:

[error]       val thing = new Thing("Franky")
[error]                       ^
[error] one error found
[error] (test:compileIncremental) Compilation failed

Now it is time to fix the tests and get them to pass. //thing.scala

class Thing(name: String) {
  def speak = {
    s"I am $name"
  }
}

Run sbt test again and you should get:

[info] ThingTests:
[info] object responds
[info] - says hello
[info] All tests passed.

Well there it is. Fun times using FunSpec.