Scala Test-Driven Development
上QQ阅读APP看书,第一时间看更新

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: