ScalaTest

Getting started with FeatureSpec

In a FeatureSpec, you describe scenarios of features. The structure looks like this:

import org.scalatest.FeatureSpec
 
class ExampleSpec extends FeatureSpec {
 
  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-1.0.jar ExampleSpec.scala

When you run it, the feature/scenario structure shows up in the output:

$ scala -cp scalatest-1.0.jar org.scalatest.tools.Runner -p . -o -s 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
import org.scalatest.GivenWhenThen
 
class ExampleSpec extends FeatureSpec 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.0.jar org.scalatest.tools.Runner -p . -o -s 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
import org.scalatest.GivenWhenThen
import scala.collection.mutable.Stack
 
class ExampleSpec extends FeatureSpec 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[String]
 
      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)
    }
  }
}

Or, if you prefer ScalaTest's matcher syntax, you can mix in ShouldMatchers or MustMatchers, like this:

import org.scalatest.FeatureSpec
import org.scalatest.GivenWhenThen
import org.scalatest.matchers.MustMatchers
import scala.collection.mutable.Stack
 
class ExampleSpec extends FeatureSpec with GivenWhenThen with MustMatchers {
 
  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")
      result must be === 2
 
      and("the stack should have one less item than before")
      stack.size must be === oldSize - 1
    }
 
    scenario("pop is invoked on an empty stack") {
 
      given("an empty stack")
      val emptyStack = new Stack[String]
 
      when("when pop is invoked on the stack")
      then("NoSuchElementException should be thrown")
      evaluating { emptyStack.pop() } must produce [NoSuchElementException]
 
      and("the stack should still be empty")
      emptyStack must be ('empty)
    }
  }
}

Now when you run ExampleSpec you'll see the tests are no longer reported as pending:

$ scala -cp scalatest-1.0.jar org.scalatest.tools.Runner -p . -o -s 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.

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 Artima, Inc. All Rights Reserved.

artima