Testing in Scala (Frameworks, Code Coverage, Mocking, Matchers, and ScalaTest)

Knoldus Blog Audio
Reading Time: 5 minutes

We will be covering the below concepts in this blog:

  • Why we need testing
  • Test Libraries
  • How to set up ScalaTest
  • Different frameworks in ScalaTest and how to use them
  • Mocking 
  • Matchers
  • Plugins for Code Coverage

Why we need testing:

Firstly, as a good software developers it is important to use testing that is good and has good coverage. Testing is an essential part of software development because it ensures that our software is reliable and stable. Moreover, testing early on in the development process ensures that any additional features being added are being added onto a well working base which helps save time in the long run. 

Testing Libraries in Scala:

In Scala we have two major testing libraries that can be used. The most popular Scala testing library is ScalaTest. We can also use JUnit, because although it is made for Java, it is compatible with Scala as well. 

We will be discussing how to use ScalaTest. First you will need to set up ScalaTest. In order to do that you can follow the instructions on this website: https://docs.scala-lang.org/getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.html

There are seven frameworks that can be used in ScalaTest. Each framework is used to help format the syntax of our test cases and each has their own pros and cons. 

The seven frameworks and their benefits are:

  1. FunSuite
  2. FlatSpec
  3. FunSpec
  4. WordSpec
  5. FreeSpec
  6. PropSpec
  7. FeatureSpec

FunSuite:

Benefits/when to use:

  • Write tests with our chosen statement
  • Easy to understand output (because it reads similar to specifications)
  • Focused tests

Example of it in code: 

https://www.scalatest.org/scaladoc/1.8/org/scalatest/FunSuite.html

FlatSpec:

Benefits/when to use:

  • X should Y format for all tests
  • Easy to find the part of code that is failing or the requirement that isn’t holding up

Example of it in code:

https://www.scalatest.org/scaladoc/1.8/org/scalatest/FlatSpec.html

FunSpec:

Benefits/when to use:

  • Ideal for Behaviour Driven Development
  • Lots of nesting which 
  • it easy to read

Example of it in code:

https://www.scalatest.org/getting_started_with_fun_spec

WordSpec:

Benefits/when to use:

  • Describes exactly how a test should be written
  • Good for ensuring that all tests and outputs are uniform
  • Will be good for teams to use a uniform approach for all of their test cases

Example of it in code:

https://www.scalatest.org/scaladoc/1.8/org/scalatest/WordSpec.html

FreeSpec:

Benefits/when to use:

  • Test writer has absolute freedom
  • Ideal for Behaviour Driven Development

Example of it in code:

https://www.scalatest.org/scaladoc/1.5/org/scalatest/FreeSpec.html

PropSpec:

Benefits/When to use:

  • Only allows for one property to be tested in each test
  • Makes debugging easier because there are fewer things being tested (so it’s easier to find errors when fixing failed test cases)
  • May lead to too many test cases

Example of it in code can be found at https://www.scalatest.org/scaladoc/1.5/org/scalatest/PropSpec.html 

FeatureSpec:

Benefits/When to use:

  • Ideal for acceptance testing

Example of it in code:

https://www.scalatest.org/getting_started_with_feature_spec

Mocking:

Next we will be discussing Mocking. Mocking is a testing method that allows us to make tests truly independent. In addition, Mocking is a testing technique that is used in testing when the unit of code being tested has dependencies.

It works by creating “mock classes” and “mock objects” which have the functionalities of classes that the code being tested depends on. For example, suppose we have a class Store that depends on the class Inventory. If we wanted to, we could write tests for Store. Then, suppose a coworker changes your project and sends it back to you. You run the previous test and find that they no longer run.

The problem is that you aren’t sure if the errors are a result of the class Store being changed or the class Inventory so you need to go back and check both classes. This might seem tedious at best at the moment but imagine if Inventory depended on other classes which depended on even more classes. Soon we run into trouble and testing could take forever!

With mocking we create “mock classes” and “mock objects” which mimic the behaviour of actual classes and objects. For example, if we were testing Store then we would create a mock class of Inventory. These mock objects and classes allow us to mimic the original classes and object’s behaviours while removing their dependencies. This allows our test to be fully independent. 

We can use frameworks such as Mockito, JMock, EasyMock or any other Java mocking framework to set up our mock objects and classes instead of doing so manually. 

Matchers:

Moreover in Scala we also have matchers. Matchers are used in testing to compare values to the expected results. 

A few examples of what you can use matchers for includes:

  • Checking equality, size or length, strings etc
  • Greater than or less than 
  • Comparing to objects to see if they are the same
  • Testing output for invalid values (ex. Null or empty)
  • And many more! (a complete list can be found here: https://www.scalatest.org/user_guide/using_matchers  )

Code Coverage:

Lastly, it is important to check and see that our test cases cover a good portion of our test (80% or more is ideal). Another way of saying this is by saying that our code coverage should be at least 80% or more. 

Code coverage is the percentage of lines that are covered by our tests. For example, suppose we have the following code:

  1. Boolean a = user.input
  2. if (a){
  3. print(“Hello this is true!”)
  4. }else{
  5. print(“Hello this is false!”)
  6. }

If our test case is used to see if “Hello this is true!” is run when a is true then we will be using lines 1, 2, and 3. But, we aren’t testing the rest of the lines since that block of code is not looked at! 

Thankfully we don’t need to check code coverage manually. We can use a plug in to do it. The plug-in will show us a breakdown of each class and how much of that class (in percent) has been covered by our tests. Plugins that you can use for code coverage include:

  • JaCoCo
  • Scoverage (Available for both SBT and Maven)
  • Cobertura
  • Any other Java code coverage plugin

Leave a Reply