Unit Testing, Test and Behaviour Driven development in Scala with JUnit

Reading Time: 7 Minutes

by Navdeep Singh Gill | November 10, 2017  Unit Testing, Test and Behaviour Driven development in Scala with JUnit

Overview

With the evolutionary growth of the software development process, Test Driven Development is an approach that consolidates test first driven methodology and refactoring.

Test Driven Development is a key practice for extreme programming, it suggests that the code is developed or changed exclusively on the basis of the Unit Testing.


TDD (Test Driven Development)

It is a practice of writing a (failing) test prior to writing the code of a feature. Feature code is refined until it passes the unit test.

Steps for the same are given below -

  • Firstly, add a test.

  • Run all the tests and see if any new test fails.

  • Update the code to make it pass the new tests.

  • Run the test again and if they fail then refactor again and repeat.

Test Driven Development Approach


BDD (Behaviour Driven Development)

Behaviour Driven Development (BDD) is similar to the Test Driven Development. In other words, Behaviour Driven Development is the extended version of Test Driven Development.

The process is similar to Test Driven Development. In this also, the code is first written in Behaviour Driven Development and the production code. But, the main difference is that in Behaviour Driven Development the test is written in plain descriptive English type grammar as opposed to Test Driven Development.

This type of development -

  • Explained the behaviour of the software/program.

  • User friendly

The major benefit of Behaviour Driven Development is that it can easily be understood by a non-technical person also.


What is Unit Testing?

Unit tests operate on a low level and are tightly coupled with source code. In the best of worlds, one unit test always correlates to one minimal piece of functionality. These functionalities are independent of the other components of the code


What is Integration Testing?

Integration tests validate that software components work correctly when combined together. Only the interfaces between components are tested and it is assumed that each component has been individually unit tested.


Test Driven Development Workflow

Test Driven Development promotes the idea of each test case testing one piece of functionality at a time. The workflow of Test Driven Development is as follows - 

  • Write a concise, minimal test for a new piece of functionality. This test will fail since the functionality isn’t implemented yet (if it passes one knows that the functionality either already exists or that the test isn’t designed correctly).

  • Implement the new functionality and run all tests, both the new and pre-existing ones. Repeat until all tests pass.

  • Clean up the code and ensure that all tests still pass, then return to step 1.

Core Overview to Test Driven Development


Test First Development in Agile

  • For this programming approach we write the tests before programming and during testing for functionality, all these test cases are run whenever we test the functionality.

  • For test first programming we can also say that we are going to write the automated test cases before the functionality and the developer has to write the test case to satisfy these tests cases.


Test Driven Development

It is the practice of first writing a (failing) test prior to writing the code for a feature. Feature code is refined until it passes tests(s).

  • Firstly when we go to design or implement a new feature we check whether an existing design is the best design which will help us to implement a new functionality.

  • If the above condition satisfies then we follow the TFD approach for the implementation of new functionality.

If the above condition is not satisfied, then it allows us to change the portion of design affected by new functionality and allows us to add new features very easily.

You May also Love to Read Test Driven Development in Java


Need For Test Driven Development

  • Ensures quality - It helps in ensuring the quality by focusing on requirements before writing the code.

  • Keeps code neat and tidy - It assists in keeping the code clear, simple and testable by breaking it down into small achievable steps.

  • Maintains Documentation - It provides documentation about how the system works for anyone coming into the team later.

  • Repeatable Test and rapid change - It builds a suite of repeatable regression tests and acts as an enabler for rapid change.


TDD Life Cycle

  • Firstly, we write the test cases.

  • Then we run these test cases with functionality.

  • Next, changes are made to the functionality if the test is not satisfied.

  • The whole process written above is repeated until the test cases are not satisfied by functionality.


Test Driven Development with Scala

Scala is a programming language which combines both object-oriented and functional programming paradigms. Considering functional aspects of Scala we can define functions of two types -

  • Functions that perform computation and no I/O operations -

    • In general, the developer must focus on writing functions which are free of side effects.

    • If the function does have side effects, those should not affect the results of subsequent tests.

  • Functions that perform I/O operations and no computation -

    • If a function performs less computation and more IO operations, one must consider specific testing frameworks for writing test for such functions. For example, there is no need to use ScalaTest (a popular testing framework) for such functions.

In scala, tests reside in project source but separated from the application code. There are many many testing frameworks available with a lot of features, one can choose according to the specific features in the framework. We will consider ScalaTest, a popular testing framework, in this document.


TDD Style Unit Tests with ScalaTest

ScalaTest is a testing framework inspired by JUnit. ScalaTest supports different styles of writing test, each designed to address specific needs.

Some of the testing styles include - 

Every member of the team is supposed to follow the same chosen style.

Scala test recommends FlatSpec for the unit and integration testing and FeatureSpec for acceptance testing.


Setting Up Environment For TDD

Perform the following steps -

  • Setup directory structure of your project as given below -


	|-- build.sbt
|-- lib
|-- project
|-- src
|   |-- main
|   |   |-- java
|   |   |-- resources
|   |   |-- scala
|   |-- test
|       |-- java
|       |-- resources
|       |-- scala
|-- target

  • Include ScalaTest in your sbt project by simply adding the following line: libraryDependencies += "org.scalatest" % "scalatest_2.12" % "3.0.4" % "test"


Implementing Test Driven Development

  • Write a test using the FlatSpec style -

import org.scalatest.FlatSpec
class PizzaTests extends FlatSpec {
 val pizza = new Pizza "A new pizza"
 should "have zero toppings" in {
  assert(pizza.getToppings.size == 0)
 }
 "A pizza"
 should "have one topping" in {
  pizza.addTopping(Topping("green olives"))
  assert(pizza.getToppings.size === 1)
 }
 it must "get pizza pricing"
 is(pending)
}

  • Write just enough code to fail the test

class Pizza {
 private val toppings = new ArrayBuffer[Topping]
 def addTopping(t: Topping) {}
 def removeTopping(t: Topping) {}
 def getToppings = toppings.toList
}

  • Execute the "sbt test" command in the project structure -

Output -

Test Output For Test Driven Development

  • Refactor the code 

import scala.collection.mutable.ArrayBuffer
case class Topping(name: String)
class Pizza {
 private val toppings = new ArrayBuffer[Topping]
 def addTopping(t: Topping) {
  toppings += t
 }
 def removeTopping(t: Topping) {
  toppings -= t
 }
 def getToppings = toppings.toList
}

  • Execute "sbt run"

Output -

Executing Test Command For TDD


Summary

Test-driven development (TDD) is a development technique where the developer must first write a test that fails before one writes new functional code. TDD ensures a proven way to ensure effective unit testing however it does not replace traditional testing.

We believe that TDD is an incredible practice that all software developers should consider during the development process.


How Can XenonStack Help You?

XenonStack follows the Test Driven Development Approach in the development of Enterprise level Applications following Agile Scrum Methodology.

  • Big Data Analysis with Scala and Apache Spark

Apache Spark enables in-memory distributed datasets that optimize workloads in addition to interactive queries. Apache Spark uses Scala as its application framework for manipulating distributed datasets as locally collective objects. Deliver highly scalable and effective Big Data Analytics Application with production grade implementation. Realize your business potential with Big Data Analysis services and data-driven decision making. 

  • Reactive Programming with Akka Framework and Scala

Harness Reactive Programming to build scalable and fault-tolerant distributed system using Scala and Akka Framework. Reactive Programming in Scala and Akka provides the platform to develop resilient, Internet Scale Applications. 

  • Scala Web and Application Development

Build Scalable and Flexible Scala Applications using Play Framework and Akka Framework. Leverage our Scala Proficiency to bring your Scala Application to market. Deploy and Manage your Scala Application on Leading Cloud Service Providers like Google Cloud, Microsoft Azure, AWS, and on Container Environment - Docker and Kubernetes.