
ScalaTest
ScalaTest has arguably become the most popular and widely used testing library for writing unit tests when programming in Scala. It is an excellent framework for writing meaningful tests that are not very verbose. The tests are readable. ScalaTest provides the flexibility of being able to write tests in various styles. This makes it a comprehensive framework for both BDD and TDD. We will be discussing BDD in more detail in later chapters.
ScalaTest also integrates very well with various third party frameworks such as JUnit, TestNG, Ant, Maven, SBT, ScalaCheck, JMock, EasyMock, Mockito, ScalaMock, Selenium, and so on. ScalaTest also integrates with IDEs like Eclipse, NetBeans, and IntelliJ.
A quick tutorial
Let's look at ScalaTest in a little more depth with the help of this quick tutorial. All the relevant documentation for ScalaTest is available on the official ScalaTest website: http://www.scalatest.org. There are some more third-party tutorials available freely on the Internet.
Adding ScalaTest to the project
The first and foremost thing to start using ScalaTest is to download ScalaTest and the related artifacts as dependencies in your project. As already mentioned, we will be using SBT for build and dependency management.
To add ScalaTest to your project, add the following dependency to your build.sbt
file:
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" % "test"
If you are using Maven, use:
<dependency> <groupId>org.scalatest</groupId> <artifactId>scalatest_2.10</artifactId> <version>2.2.6</version> <scope>test</scope> </dependency>
Tip
Use the version of ScalaTest that is compatible with your version of Scala.
Note
We covered a very simple ScalaTest example in Chapter 1, Hello, TDD!. If you skipped that chapter, I would suggest implementing that example before we move forward.
Choose your testing style
A major advantage of using ScalaTest is that it supports a different style of testing. Each style caters to a different set of needs, and it is up to the developer to choose the best style for the type of project. In practice, it is advisable to use the same testing style throughout the project, so there is uniformity in testing and code that can be reused or refactored later.
I sometimes use two different styles in my project, one for unit testing and another for functional testing. This makes it easier to look at the test and know if it can be run in isolation, as is the case with most unit tests. It is recommended to use FlatSpec for unit testing and FeatureSpec for functional or acceptance testing.
Let's look at all the styles briefly.
FunSuite
This is good for the transition from xUnit with vivid test names:
import org.scalatest.FunSuite class AddSuite extends FunSuite { test("3 plus 3 is 6") { assert((3 + 3) == 6) } }
FlatSpec
The structure of this test is flat—like xUnit, but the test name can be written in specification style:
import org.scalatest.FlatSpec class AddSpec extends FlatSpec { "Addition of 3 and 3" should "have result 6" in { assert((3 + 3) == 0) } }
FunSpec
This is more analogous to Ruby's RSpec:
import org.scalatest.FunSpec class AddSpec extends FunSpec{ describe("Addition") { describe("of 3 and 3") { it("should have result 6") { assert((3 + 3) == 6) } } } }
WordSpec
This has a similar structure to Specs2:
import org.scalatest.WordSpec class AddSpec extends WordSpec { "Addition" when { "of 3 and 3" should { "have result 6" in { assert((3 + 3) == 6) } } } }
FreeSpec
This gives outright freedom on specification text and structure:
import org.scalatest.FreeSpec class AddSpec extends FreeSpec { "Addition" - { "of 3 and 3" - { "should have result 6" in { assert((3 + 3) == 6) } } } }
Spec
This allows you to define tests as methods:
import org.scalatest.Spec class AddSpec extends Spec { object `Addition` { object `of 3 and 3` { def `should give result 6` { assert((3 + 3) == 6) } } } }
PropSpec
This is used for writing tests that are driven through a matrix of data:
import org.scalatest._ import prop._ class AddSpec extends PropSpec with TableDrivenPropertyChecks with Matchers { val examples = Table( ("a", "b", "result"), (3, 3, 6), (4, 5, 9) ) property("Addition of two numbers") { forAll(examples) { (a, b, result) => (a + b) should be (result) } } }
FeatureSpec
This is primarily intended for writing BDD style acceptance tests. This allows for the use of ubiquitous language that can be understood by non-programmers:
import org.scalatest._ class Calculator { def add(a:Int, b:Int): Int = a + b } class CalcSpec extends FeatureSpec with GivenWhenThen { info("As a calculator owner") info("I want to be able add two numbers") info("so I can get a correct result") feature("Addition") { scenario("User adds two numbers") { Given("a calculator") val calc = new Calculator When("two numbers are added") var result = calc.add(3, 3) Then("we get correct result") assert(result == 6) } } }
Note
Most of the book's examples will be built using FlatSpec and FeatureSpec.
Resources for ScalaTest
Further tutorials and documentation on ScalaTest are available here: