FeatureSpec
By learning to use FeatureSpec
, GivenWhenThen
, simple assertions, and the BeforeAndAfter
trait, you can become
productive in the acceptance testing style of ScalaTest very quickly. You can then learn and use more of ScalaTest over time.
In a FeatureSpec
, you describe scenarios of features. The structure looks like this:
import org.scalatest.featurespec.AnyFeatureSpec class ExampleSpec extends AnyFeatureSpec { Feature("The user can pop an element off the top of the stack") { Scenario("pop is invoked on a non-empty stack") (pending) Scenario("pop is invoked on an empty stack") (pending) } }
Each scenario in a FeatureSpec
is one ScalaTest test. The scenarios are marked pending in the previous example
to indicate the tests have not yet been implemented. You can compile this FeatureSpec
like this:
$ scalac -cp scalatest-3.2.19.jar ExampleSpec.scala
When you run it, the feature/scenario structure shows up in the output:
$ scala -cp scalatest-3.2.19.jar org.scalatest.run ExampleSpec Run starting. Expected test count is: 2 ExampleSpec: Feature: The user can pop an element off the top of the stack Scenario: pop is invoked on a non-empty stack (pending) Scenario: pop is invoked on an empty stack (pending) Run completed in 65 milliseconds. Total number of tests run: 0 Suites: completed 1, aborted 0 Tests: succeeded 0, failed 0, ignored 0, pending 2 All tests passed.
If you wish, you can flesh out the specification by mixing in GivenWhenThen
and adding extra information about the scenarios, like this:
import org.scalatest.featurespec.AnyFeatureSpec import org.scalatest.GivenWhenThen class ExampleSpec extends AnyFeatureSpec with GivenWhenThen { Feature("The user can pop an element off the top of the stack") { info("As a programmer") info("I want to be able to pop items off the stack") info("So that I can get them in last-in-first-out order") Scenario("pop is invoked on a non-empty stack") { Given("a non-empty stack") When("when pop is invoked on the stack") Then("the most recently pushed element should be returned") And("the stack should have one less item than before") pending } Scenario("pop is invoked on an empty stack") { Given("an empty stack") When("when pop is invoked on the stack") Then("NoSuchElementException should be thrown") And("the stack should still be empty") pending } } }
When you run this version of ExampleSpec
, you'll see the extra information in the report:
$ scala -cp scalatest-1.8.jar org.scalatest.run ExampleSpec Run starting. Expected test count is: 2 ExampleSpec: Feature: The user can pop an element off the top of the stack As a programmer I want to be able to pop items off the stack So that I can get them in last-in-first-out order Scenario: pop is invoked on a non-empty stack (pending) Given a non-empty stack When when pop is invoked on the stack Then the most recently pushed element should be returned And the stack should have one less item than before Scenario: pop is invoked on an empty stack (pending) Given an empty stack When when pop is invoked on the stack Then NoSuchElementException should be thrown And the stack should still be empty Run completed in 112 milliseconds. Total number of tests run: 0 Suites: completed 1, aborted 0 Tests: succeeded 0, failed 0, ignored 0, pending 2 All tests passed.
When you can't put off writing the actual tests themselves any longer, you can fill them in. Here's an example:
import org.scalatest.featurespec.AnyFeatureSpec import org.scalatest.GivenWhenThen import scala.collection.mutable.Stack class ExampleSpec extends AnyFeatureSpec with GivenWhenThen { Feature("The user can pop an element off the top of the stack") { info("As a programmer") info("I want to be able to pop items off the stack") info("So that I can get them in last-in-first-out order") Scenario("pop is invoked on a non-empty stack") { Given("a non-empty stack") val stack = new Stack[Int] stack.push(1) stack.push(2) val oldSize = stack.size When("when pop is invoked on the stack") val result = stack.pop() Then("the most recently pushed element should be returned") assert(result === 2) And("the stack should have one less item than before") assert(stack.size === oldSize - 1) } Scenario("pop is invoked on an empty stack") { Given("an empty stack") val emptyStack = new Stack[Int] When("when pop is invoked on the stack") Then("NoSuchElementException should be thrown") intercept[NoSuchElementException] { emptyStack.pop() } And("the stack should still be empty") assert(emptyStack.isEmpty) } } }
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: Feature: The user can pop an element off the top of the stack As a programmer I want to be able to pop items off the stack So that I can get them in last-in-first-out order Scenario: pop is invoked on a non-empty stack Given a non-empty stack When when pop is invoked on the stack Then the most recently pushed element should be returned And the stack should have one less item than before Scenario: pop is invoked on an empty stack Given an empty stack When when pop is invoked on the stack Then NoSuchElementException should be thrown And the stack should still be empty Run completed in 96 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.featurespec.AnyFeatureSpec import org.scalatest.GivenWhenThen import org.scalatest.BeforeAndAfter import scala.collection.mutable.Stack class ExampleSpec extends AnyFeatureSpec with GivenWhenThen with BeforeAndAfter { var stack: Stack[Int] = _ before { stack = new Stack[Int] } Feature("The user can pop an element off the top of the stack") { info("As a programmer") info("I want to be able to pop items off the stack") info("So that I can get them in last-in-first-out order") Scenario("pop is invoked on a non-empty stack") { Given("a non-empty stack") stack.push(1) stack.push(2) val oldSize = stack.size When("when pop is invoked on the stack") val result = stack.pop() Then("the most recently pushed element should be returned") assert(result === 2) And("the stack should have one less item than before") assert(stack.size === oldSize - 1) } Scenario("pop is invoked on an empty stack") { Given("an empty stack") When("when pop is invoked on the stack") Then("NoSuchElementException should be thrown") intercept[NoSuchElementException] { stack.pop() } And("the stack should still be empty") assert(stack.isEmpty) } } }
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: Feature: The user can pop an element off the top of the stack As a programmer I want to be able to pop items off the stack So that I can get them in last-in-first-out order Scenario: pop is invoked on a non-empty stack Given a non-empty stack When when pop is invoked on the stack Then the most recently pushed element should be returned And the stack should have one less item than before Scenario: pop is invoked on an empty stack Given an empty stack When when pop is invoked on the stack Then NoSuchElementException should be thrown And the stack should still be empty Run completed in 96 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 acceptance 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-2025 Artima, Inc. All Rights Reserved.