FunSpec
By learning to use FunSpec
, simple assertions, and the BeforeAndAfter
trait, you can become
productive in the BDD style of ScalaTest very quickly. You can then learn and use more of ScalaTest over time.
In a FunSpec
, you combine tests with text that specifies the behavior being tested.
You can describe the subject being specified and tested with describe
clauses and
place text that describes the behavior expected of the subject in it
clauses.
The code of the test appears in curly braces after the it
and its text. The structure looks like this:
import org.scalatest.funspec.AnyFunSpec class ExampleSpec extends AnyFunSpec { describe("A Stack") { it("should pop values in last-in-first-out order") (pending) it("should throw NoSuchElementException if an empty stack is popped") (pending) } }
Here the subject being specified and tested is “A Stack.” The tests are marked pending in the previous example
to indicate the tests have not yet been implemented. You can compile this FunSpec
like this:
$ scalac -cp scalatest-3.2.19.jar ExampleSpec.scala
Here's how you run it:
$ scala -cp scalatest-3.2.19.jar org.scalatest.run ExampleSpec Run starting. Expected test count is: 2 ExampleSpec: A Stack - should pop values in last-in-first-out order (pending) - should throw NoSuchElementException if an empty stack is popped (pending) Run completed in 61 milliseconds. Total number of tests run: 0 Suites: completed 1, aborted 0 Tests: succeeded 0, failed 0, ignored 0, pending 2 All tests passed.
Notice that the specification text appears in a readable form in the output. You could fill in the tests like this:
import org.scalatest.funspec.AnyFunSpec import scala.collection.mutable.Stack class ExampleSpec extends AnyFunSpec { describe("A Stack") { it("should pop values in last-in-first-out order") { val stack = new Stack[Int] stack.push(1) stack.push(2) assert(stack.pop() === 2) assert(stack.pop() === 1) } it("should throw NoSuchElementException if an empty stack is popped") { val emptyStack = new Stack[Int] intercept[NoSuchElementException] { emptyStack.pop() } } } }
Now when you run ExampleSpec
you'll see the tests are no longer reported as pending:
$ scala -cp scalatest-3.2.19.jar org.scalatest.run ExampleSpec Run starting. Expected test count is: 2 ExampleSpec: A Stack - should pop values in last-in-first-out order - should throw NoSuchElementException if an empty stack is popped Run completed in 76 milliseconds. Total number of tests run: 2 Suites: completed 1, aborted 0 Tests: succeeded 2, failed 0, ignored 0, pending 0 All tests passed.
To get started quickly with ScalaTest, learn to use assert
with the ===
operator
and intercept
. Later if you prefer you can switch to ScalaTest's matchers.
ScalaTest lets you use Scala's assertion syntax, but defines a triple equals operator (===
) to give you better error messages. The following
code would give you an error indicating only that an assertion failed:
assert(1 == 2)
Using triple equals instead would give you the more informative error message, "1 did not equal 2"
:
assert(1 === 2)
To test whether a bit of code produces an expected exception, use intercept
. Place the expected exception type in
square brackets after intercept
, and the bit of code in curly braces, like this:
val s = "hi" intercept[IndexOutOfBoundsException] { s.charAt(-1) }
If the bit of code between the curly braces throws the expected exception, intercept
will return it. In the previous example that return value was ignored.
If you want to inspect the thrown exception, you can do so like this:
val s = "hi" val thrown = intercept[IndexOutOfBoundsException] { s.charAt(-1) } assert(thrown.getMessage === "String index out of range: -1")
If the bit of code between the curly braces throws the wrong exception, or does not throw any exception, you'll get a test failure describing the problem.
If you want to factor out duplicate code from tests, mix in BeforeAndAfter
, surround the code you
want to run before each test by before { ... }
, and after each test by after { ... }
. Here's an example that just uses before
:
import org.scalatest.funspec.AnyFunSpec import org.scalatest.BeforeAndAfter import scala.collection.mutable.Stack class ExampleSpec extends AnyFunSpec with BeforeAndAfter { var stack: Stack[Int] = _ before { stack = new Stack[Int] } describe("A Stack") { it("should pop values in last-in-first-out order") { stack.push(1) stack.push(2) assert(stack.pop() === 2) assert(stack.pop() === 1) } it("should throw NoSuchElementException if an empty stack is popped") { intercept[NoSuchElementException] { stack.pop() } } } }
You compile and run it the same way:
$ scalac -cp scalatest-3.2.19.jar ExampleSpec.scala $ scala -cp scalatest-3.2.19.jar org.scalatest.run ExampleSpec Run starting. Expected test count is: 2 ExampleSpec: A Stack - should pop values in last-in-first-out order - should throw NoSuchElementException if an empty stack is popped Run completed in 76 milliseconds. Total number of tests run: 2 Suites: completed 1, aborted 0 Tests: succeeded 2, failed 0, ignored 0, pending 0 All tests passed.
Armed with this knowledge, you can already write real BDD-style tests with ScalaTest. To go further, check out the user guide.
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.