ScalaTest User Guide

Writing your first test

Using assertions

Tagging your tests

Running your tests

Sharing fixtures

Sharing tests

Using matchers

Testing with mock objects

Tests as specifications

Property-based testing

Other goodies

Philosophy and design

Selecting a style

Using assertions

ScalaTest makes three assertions available by default in any style trait. You can use:

  • assert with ===, for general assertions;
  • expect, to differentiate expected from actual values;
  • intercept, to ensure a bit of code throws an expected exception.

To get moving quickly in ScalaTest, learn and use these three assertions. Later if you prefer you can switch to the more expressive matchers DSL.

In any Scala program, you can write assertions by invoking assert and passing in a Boolean expression, such as:

val left = 2
val right = 1
assert(left == right)

If the passed expression is true, assert will return normally. If false, assert will complete abruptly with an AssertionError. This behavior is provided by the assert method defined in object Predef, whose members are implicitly imported into every Scala source file.

ScalaTest defines another assert method that hides the one in Predef. It behaves the same, except that if false is passed it throws TestFailedException instead of AssertionError. The reason it throws TestFailedException is because TestFailedException carries information about exactly which item in the stack trace represents the line of test code that failed, which can help users more quickly find an offending line of code in a failing test.

If you pass the previous Boolean expression, left == right to assert in a ScalaTest test, a failure will be reported, but without reporting the left and right values. You can alternatively encode these values in a String passed as a second argument to assert, like this:

val left = 2
val right = 1
assert(left == right, left + " did not equal " + right)

Using this form of assert, the failure report will include the left and right values, thereby helping you debug the problem. However, ScalaTest provides the === operator to make this easier. You use it like this:

val left = 2
val right = 1
assert(left === right)

Because you use === here instead of ==, the failure report will include the left and right values. For example, the detail message in the thrown TestFailedException from the assert shown previously will include, "2 did not equal 1". From this message you will know that the operand on the left had the value 2, and the operand on the right had the value 1.

Expected results

Although === provides a natural, readable extension to Scala's assert mechanism, as the operands become lengthy, the code becomes less readable. In addition, the === comparison doesn't distinguish between actual and expected values. The operands are just called left and right, because if one were named expected and the other actual, it would be difficult for people to remember which was which. To help with these limitations of assert, ScalaTest provides a method called expect that can be used as an alternative to assert with ===. To use expect, you place the expected value in parentheses after expect, followed by curly braces containing code that should result in the expected value. For example:
val a = 5
val b = 2
expect(2) {
  a - b
}

In this case, the expected value is 2, and the code being tested is a - b. This expectation will fail, and the detail message in the TestFailedException will read, "Expected 2, but got 3."

Intercepted exceptions

Sometimes you need to test whether a method throws an expected exception under certain circumstances, such as when invalid arguments are passed to the method. You can do this in the JUnit 3 style, like this:

val s = "hi"
try {
  s.charAt(-1)
  fail()
}
catch {
  case _: IndexOutOfBoundsException => // Expected, so continue
}

If charAt throws IndexOutOfBoundsException as expected, control will transfer to the catch case, which does nothing. If, however, charAt fails to throw an exception, the next statement, fail(), will be run. The fail method always completes abruptly with a TestFailedException, thereby signaling a failed test.

To make this common use case easier to express and read, ScalaTest provides an intercept method. You use it like this:

val s = "hi"
intercept[IndexOutOfBoundsException] {
  s.charAt(-1)
}

This code behaves much like the previous example. If charAt throws an instance of IndexOutOfBoundsException, intercept will return that exception. But if charAt completes normally, or throws a different exception, intercept will complete abruptly with a TestFailedException. intercept returns the caught exception so that you can inspect it further if you wish, for example, to ensure that data contained inside the exception has the expected values. Here's an example:

val s = "hi"
val thrown = intercept[IndexOutOfBoundsException] {
  s.charAt(-1)
}
assert(thrown.getMessage === "String index out of range: -1")

Next, learn about tagging your tests.

ScalaTest is brought to you by Bill Venners, with contributions from several other folks. It is sponsored by Artima, Inc.
ScalaTest is free, open-source software released under the Apache 2.0 license.

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

artima