ScalaTest: A Beginner’s Guide

Zubair Haque
3 min readJan 15, 2019

If you’re working on a service that is written in Scala, this documentation will aide you in the setup of your test suite. The ScalaTest documentation can be found here (Note: This post will dive into the following topics in detail):

  • Adding ScalaTest to your build.sbt
  • Writing your first Test Class
  • Matchers
  • Running Tests
  • Tagging Tests

sbt

The sbt documentation explains in detail what’s being used and what’s being built when your project compiles. All of these things are stored in your build.sbt file, which lives in your projects base directory. Here’s an example of how to add dependencies to your test suite:

libraryDependencies ++= Seq(
"org.json4s" %% "json4s-native" % "version",
"org.json4s" %% "json4s-jackson" % "version",
"io.rest-assured" % "scala-support" % "version",
"io.rest-assured" % "json-schema-validator" % "version",
"org.scalatest" %% "scalatest" % "version"
)

The dependencies listed below are the jar files I prefer to use:

json4s: I'm adding in json4s, which is a serialization library I use to parse requests returned from the server.
rest-assured: is a DSL used for writing & maintaining tests for RESTful APIs.

Now that we’ve added our dependencies, let’s create and configure our test directory (this is where where you can define an abstract base class, the test runner itself & most importantly the tests). The directory structure for your tests should look like this:

  • src/test/scala/
  • Then a resources directory for the classpath in src/test/resources/

Test Classes

Before we actually create our first test class, it’s a good idea to create an abstract class which we’ll refer to as the BaseClass: this approach let’s us reuse all the common code and makes the suite more DRY:

package com.project.service.integration.testsimport org.scalatest._abstract class BaseClass extends Funspec with Matchers {//add common behavior that can be extended in the Test Class}

Once you’ve created your BaseClass, you can extend it throughout your test suite. So now each one of your test classes in your test suite can extend your BaseClass.

package com.project.service.integration.tests.apiimport org.scalatest._
import com.project.service.integration.tests.BaseClass
import io.restassured.module.scala.RestAssuredSupport._
import org.json4s.native.JsonMethods._

class TestSpec extends BaseCiTest {
//define test functions below
}

So above is a basic example on how to define a test class in Scala. Fun fact: Scalatest has many styles, my style of choice is FunSpec, which derives from my familiarity with RSpec. The styling of my previous suite was somewhat similar: It began with a describe statement to test the API, followed by nested it statements testing the various scenarios:

describe("POST /v1/endpoint") {
it("Create a user in the system") {
//test and validate your user story
}
}

Matchers

ScalaTest has a rich set of matchers that should be taken advantage of, listed below is an http response code:

describe("POST /v1/endpoint") {
it("Create a user in the system") {
val createUser = request(payload).post(url)
val statusCode = createUser.getStatusCode
statusCode shouldBe 201
}
}
/*
The scenario above is creating a user by making a POST request to the v1 endpoint. After the request is made we use the shouldBe matcher to validate the status code being sent back from the server.
*/

If you want to test length and size of a collection you can utilize the should have matcher here is a snippet below:

class TestSpec extends BaseCiTest
with Matchers {
describe("GET /v1/endpoint") {
it("GET length of users") {
val users = request(payload).get(url)
users should have size 5
}
}
}

Running your tests

Now that we’ve written some tests, let’s run them in the terminal. To run your entire test suite, just run:

sbt test

when typing in the test runner invokes all of your test functions to run in your test directory. To run just one class you can:

sbt "testOnly com.project.service.integration.tests.ClassName"

Tagging your tests

If you have specific changes to test, you might want to target your regression efforts to be a bit more specific. ScalaTest allows you to define test categories and filter tests to run based on their tags. From my RSpec days I remember creating rake tasks to basically run on demand when changes were made. Scalatest allows you to do the same with the addCommandAlias function. Here is an example below:

// add this example below to your build.sbt fileaddCommandAlias(
“tagName”,
"testOnly -- -n tagName”
)

The testOnly Scala filters a targeted subset tests to run. Furthermore, the -n in this case is saying include these tagged scenarios to be run.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Zubair Haque
Zubair Haque

Written by Zubair Haque

The Engineering Chronicles: I specialize in Automated Deployments

No responses yet

Write a response