TDD is a very powerful technique to write efficient, modular, and safe programs. It is very simple, and there are only three rules to play this game:
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail, and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
There are multiple testing frameworks in Scala, but we chose ScalaTest (http://www.scalatest.org/) for its simplicity.
In order to add the ScalaTest library in the project, follow these steps:
- Edit the build.sbt file.
- Add a new repository resolver to search for Scala libraries.
- Add the ScalaTest library:
name := "Examples"
version := "0.1"
scalaVersion := "2.12.4"
resolvers += "Artima Maven Repository" at "http://repo.artima.com/releases"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
Notice the information bar on the top of the screen. It tells you that your file has changed and asks for multiple choices. As this is a small project, you can select enable autoimport.
- Create the test class by right-clicking on the test/scala folder and clicking on create a new class. Name it MainSpec.
ScalaTest offers multiple ways to define your test – the full list can be found on the official website (http://www.scalatest.org/at_a_glance/WordSpec). We are going to use the WordSpec style since it is quite prescriptive, offers a hierarchical structure, and is commonly used on large Scala projects.
Your MainSpec should extend the WordSpec class and the Matchers class, like so:
class MainSpec extends WordSpec with Matchers {
}
The class Matchers is providing the word should as a keyword to perform the comparison on a test.
WordSpec and Matchers are underlined in red, which means that the class is not resolved. To make it resolved, go with the cursor on the class and press Alt + Enter of your keyboard. If you are positioned on the WordSpec word, a popup should appear. This is normal, as there are several classes named WordSpec in different packages:
Select the first option and IntelliJ will automatically add the import on the top of your code. On the Matchers class, as soon as you type Alt + Enter, the import will be added directly.
The final code should be as follows:
import org.scalatest.{WordSpec, Matchers}
class MainSpec extends WordSpec with Matchers {
}
Our class skeleton is now ready for our first test. We would like to create the Person class and test its constructor.
Let's explain what we would like to test using simple sentences. Complete the test class with the following code:
class MainSpec extends WordSpec with Matchers {
"A Person" should {
"be instantiated with a age and name" in {
val john = Person(firstName = "John", lastName = "Smith", 42)
john.firstName should be("John")
john.lastName should be("Smith")
john.age should be(42)
}
}
}
IntelliJ is complaining that it cannot resolve the symbols Person, name, surname, and age. This is expected since the Person class does not exist. Let's create it in the folder src/main/scala. Right-click on the folder and create a new class named Person.
Transform it in the case of the class by adding the case keyword and defining the constructor with the name, surname, and age:
case class Person(firstName: String, lastName: String, age: Int)
If you go back to the MainSpec.scala file, you'll notice that the class is now compiled without any error and warning. The green tick () on the top-right of the code window confirms this.
Run the test by right-clicking on the MainSpec.scala file and selecting Run 'MainSpec', or use the keyboard shortcut Ctrl + Shift + F10 or Ctrl + Shift + R:
The test contained in MainSpec runs and the results appear in the Run window: