ScalaTest User Guide

Getting started

Selecting testing styles

Defining base classes

Writing your first test

Using assertions

Tagging your tests

Running your tests

Sharing fixtures

Sharing tests

Using matchers

Testing with mock objects

Property-based testing

Asynchronous testing

Using Scala-js

Using Inside

Using OptionValues

Using EitherValues

Using PartialFunctionValues

Using PrivateMethodTester

Using WrapWith

Philosophy and design

Migrating to 3.0

Selecting testing styles for your project

ScalaTest supports different styles of testing, each designed to address a particular set of needs. To help you find the best-fit styles for your project, this page will describe the intended use cases for each option.

We recommend you choose a set of testing styles for each project, then encourage everyone working on the project use the chosen styles. This allows the testing styles to fit the team while maintaining uniformity in the project code base. We recommend you select one main style for unit testing and another for acceptance testing. Using a different style for unit and acceptance testing can help developers "switch gears" between low-level unit testing to high-level acceptance testing. You may also want to select particular styles to be used in special situations, such as using PropSpec for test matrixes. We usually write integration tests—tests that involve subsystems such as a database—in the same style as the unit tests.

In short, ScalaTest's flexibility is not intended to enable individual developers to use different testing styles on the same project. Rather, it is intended to enable project leaders to select a best-fit style or styles for the team. To help you maintain consistency of style across your project, you can specify style artifacts in your build dependencies instead of the general ScalaTest artifact. The general ScalaTest artifact (named scalatest) contains all testing styles, whereas the scalatest-flatspec artifact, for example, contains just the FlatSpec testing style.

The style you choose dictates only how the declarations of your tests will look. Everything else in ScalaTest—assertions, matchers, mixin traits, etc.—works consistently the same way no matter what style you chose.

If you don't enjoy shopping

If you would rather be told which approach to take rather than pick one yourself, we recommend you use the FlatSpec style for unit and integration testing and the FeatureSpec style for acceptance testing. We recommend the FlatSpec style as the default choice, because it is flat (unnested) like the XUnit tests familiar to most developers, but guides you into writing focused tests with descriptive, specification-style names.

Testing style use cases

If you would rather make your own choices, this table gives a quick overview of the advantages and disadvantages of each style trait. For more information and examples, click on the links:

Testing Style Descriptions and Examples

The FunSuite style

For teams coming from xUnit, the FunSuite style feels comfortable and familiar while still giving some of the benefits of BDD: the FunSuite style makes it easy to write descriptive test names, natural to write focused tests, and generates specification-like output that can facilitate communication among stakeholders.

import org.scalatest.funsuite.AnyFunSuite

class SetSuite extends AnyFunSuite {
test("An empty Set should have size 0") { assert(Set.empty.size == 0) }
test("Invoking head on an empty Set should produce NoSuchElementException") { assertThrows[NoSuchElementException] { Set.empty.head } } }

To select just the FunSuite style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-funsuite" % "3.2.18" % "test"

The FlatSpec style

A good first step for teams wishing to move from xUnit to BDD, the FlatSpec style's structure is flat like xUnit, so simple and familiar, but the test names must be written in a specification style: "X should Y," "A must B," etc.

import org.scalatest.flatspec.AnyFlatSpec

class SetSpec extends AnyFlatSpec {
"An empty Set" should "have size 0" in { assert(Set.empty.size == 0) }
it should "produce NoSuchElementException when head is invoked" in { assertThrows[NoSuchElementException] { Set.empty.head } } }

To select just the FlatSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-flatspec" % "3.2.18" % "test"

The FunSpec style

For teams coming from Ruby's RSpec tool, the FunSpec style will feel very familiar; More generally, for any team that prefers BDD, FunSpec's nesting and gentle guide to structuring text (with describe and it) provides an excellent general-purpose choice for writing specification-style tests.

import org.scalatest.funspec.AnyFunSpec

class SetSpec extends AnyFunSpec {
describe("A Set") { describe("when empty") { it("should have size 0") { assert(Set.empty.size == 0) }
it("should produce NoSuchElementException when head is invoked") { assertThrows[NoSuchElementException] { Set.empty.head } } } } }

To select just the FunSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-funspec" % "3.2.18" % "test"

The WordSpec style

For teams coming from specs or specs2, the WordSpec style will feel familiar, and is often the most natural way to port specsN tests to ScalaTest. AnyWordSpec is very prescriptive in how text must be written, so a good fit for teams who want a high degree of discipline enforced upon their specification text.

import org.scalatest.wordspec.AnyWordSpec

class SetSpec extends AnyWordSpec {
"A Set" when { "empty" should { "have size 0" in { assert(Set.empty.size == 0) }
"produce NoSuchElementException when head is invoked" in { assertThrows[NoSuchElementException] { Set.empty.head } } } } }

To select just the WordSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-wordspec" % "3.2.18" % "test"

The FreeSpec style

Because it gives absolute freedom (and no guidance) on how specification text should be written, the FreeSpec style is a good choice for teams experienced with BDD and able to agree on how to structure the specification text.

import org.scalatest.freespec.AnyFreeSpec

class SetSpec extends AnyFreeSpec {
"A Set" - { "when empty" - { "should have size 0" in { assert(Set.empty.size == 0) }
"should produce NoSuchElementException when head is invoked" in { assertThrows[NoSuchElementException] { Set.empty.head } } } } }

To select just the FreeSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-freespec" % "3.2.18" % "test"

The PropSpec style

The AnyPropSpec style is perfect for teams that want to write tests exclusively in terms of property checks; also a good choice for writing the occasional test matrix when a different style trait is chosen as the main unit testing style.

import org.scalatest._
import matchers._
import prop._
import scala.collection.immutable._

class SetSpec extends AnyPropSpec with TableDrivenPropertyChecks with should.Matchers {
val examples = Table( "set", BitSet.empty, HashSet.empty[Int], TreeSet.empty[Int] )
property("an empty Set should have size 0") { forAll(examples) { set => set.size should be (0) } }
property("invoking head on an empty set should produce NoSuchElementException") { forAll(examples) { set => a [NoSuchElementException] should be thrownBy { set.head } } } }

To select just the PropSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-propspec" % "3.2.18" % "test"

The FeatureSpec style

The FeatureSpec style is primarily intended for acceptance testing, including facilitating the process of programmers working alongside non-programmers to define the acceptance requirements.

import org.scalatest._

class TVSet { private var on: Boolean = false def isOn: Boolean = on def pressPowerButton() { on = !on } }
class TVSetSpec extends AnyFeatureSpec with GivenWhenThen {
info("As a TV set owner") info("I want to be able to turn the TV on and off") info("So I can watch TV when I want") info("And save energy when I'm not watching TV")
feature("TV power button") { scenario("User presses power button when TV is off") {
Given("a TV set that is switched off") val tv = new TVSet assert(!tv.isOn)
When("the power button is pressed") tv.pressPowerButton()
Then("the TV should switch on") assert(tv.isOn) }
scenario("User presses power button when TV is on") {
Given("a TV set that is switched on") val tv = new TVSet tv.pressPowerButton() assert(tv.isOn)
When("the power button is pressed") tv.pressPowerButton()
Then("the TV should switch off") assert(!tv.isOn) } } }

To select just the FeatureSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-featurespec" % "3.2.18" % "test"

RefSpec (JVM only)

The RefSpec style allows you to define tests as methods, which saves one function literal per test compared to style classes that represent tests as functions. Fewer function literals translates into faster compile times and fewer generated class files, which can help minimize build times. As a result, using Spec can be a good choice in large projects where build times are a concern as well as when generating large numbers of tests programatically via static code generators.

import org.scalatest.refspec.RefSpec

class SetSpec extends RefSpec {
object `A Set` { object `when empty` { def `should have size 0` { assert(Set.empty.size == 0) }
def `should produce NoSuchElementException when head is invoked` { assertThrows[NoSuchElementException] { Set.empty.head } } } } }

Note: The "Ref" in RefSpec stands for reflection, which RefSpec uses to discover tests. As reflection is not availble in Scala.js, this class is not available on Scala.js.

To select just the RefSpec style in an sbt build, include this line:

libraryDependencies += "org.scalatest" %% "scalatest-refspec" % "3.2.18" % "test"

Next, define a base class for unit testing.

ScalaTest is brought to you by Bill Venners and Artima.
ScalaTest is free, open-source software released under the Apache 2.0 license.

If your company loves ScalaTest, please consider sponsoring the project.

Copyright © 2009-2024 Artima, Inc. All Rights Reserved.

artima