04.FeatureSpec の始め方
FeatureSpec では、あなたは各機能(feature)のシナリオ(sinario)を書きます。
基本的な構文は、以下のようなものです。
import org.scalatest.FeatureSpec
class ExampleSpec extends FeatureSpec {
feature("ユーザーは、要素を stack の先頭から取り出すことができる") {
scenario("pop は空でない stack で実行される") (pending)
scenario("pop は空の stack で実行される") (pending)
}
}
FeatureSpec のそれぞれのシナリオは、ScalaTest の1つのテストに相当します。
この例では、シナリオの中身が「pending」になっていますが、これはまだテスト本体が実装されていないことを示しています。
このコードをコンパイルするには、コマンドラインから次のように入力してください。
$ scalac -cp scalatest-1.5.jar ExampleSpec.scala
これを実行すると、feature/sinario 構文は以下のような出力を表示します。
$ scala -cp scalatest-1.5.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 は空でない stack で実行される (pending)
Scenario: pop は空の 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.
もしお望みなら、GivenWhenThen トレイトをミックスインし、シナリオに説明を追加することで、仕様を具体化することができます。
import org.scalatest.FeatureSpec
import org.scalatest.GivenWhenThen
class ExampleSpec extends FeatureSpec with GivenWhenThen {
feature("ユーザーは、要素を stack の先頭から取り出すことができる") {
info("一介のプログラマとして")
info("後入れ先出しの順序でアイテムを管理するために")
info("stack からアイテムを pop で取り出せるようにしたい")
scenario("pop は空でない stack で実行される") {
given("空でない stack")
when("空でない stack で pop が実行されたとき")
then("いちばん新しく格納された要素が返されなければならない")
and("その後、stack は該当する1つのアイテムを減らさなければならない")
pending
}
scenario("pop は空の stack で実行される") {
given("空の stack")
when("pop が stack で実行されたとき")
then("NoSuchElementException が投げられなければならない")
and("stack は依然空のままでなければならない")
pending
}
}
}
このバージョンの ExampleSpec を実行すると、出力レポートに説明が追加されています。
$ scala -cp scalatest-1.5.jar org.scalatest.tools.Runner -p . -o -s
ExampleSpec
Run starting. Expected test count is: 2
ExampleSpec:
Feature: ユーザーは、要素を stack の先頭から取り出すことができる
一介のプログラマとして
後入れ先出しの順序でアイテムを管理するために
stack からアイテムを pop で取り出せるようにしたい
Scenario: pop は空でない stack で実行される (pending)
Given 空でない stack
When 空でない stack で pop が実行されたとき
Then いちばん新しく格納された要素が返されなければならない
And その後、stack は該当する1つのアイテムを減らさなければならない
Scenario: pop は空の stack で実行される (pending)
Given 空の stack
When pop が stack で実行されたとき
Then NoSuchElementException が投げられなければならない
And stack は依然空のままでなければならない
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.
もうテストの実装が先延ばしにできなくなったときが、テストの書き時です。
以下に一例を示します。
import org.scalatest.FeatureSpec
import org.scalatest.GivenWhenThen
import scala.collection.mutable.Stack
class ExampleSpec extends FeatureSpec with GivenWhenThen {
feature("ユーザーは、要素を stack の先頭から取り出すことができる") {
info("一介のプログラマとして")
info("後入れ先出しの順序でアイテムを管理するために")
info("stack からアイテムを pop で取り出せるようにしたい")
scenario("pop は空でない stack で実行される") {
given("空でない stack")
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
val oldSize = stack.size
when("空でない stack で pop が実行されたとき")
val result = stack.pop()
then("いちばん新しく格納された要素が返されなければならない")
assert(result === 2)
and("その後、stack は該当する1つのアイテムを減らさなければならない")
assert(stack.size === oldSize - 1)
}
scenario("pop は空の stack で実行される") {
given("空の stack")
val emptyStack = new Stack[String]
when("pop が stack で実行されたとき")
then("NoSuchElementException が投げられなければならない")
intercept[NoSuchElementException] {
emptyStack.pop()
}
and("stack は依然空のままでなければならない")
assert(emptyStack.isEmpty)
}
}
}
この例では assert を使いましたが、ScalaTest の Matcher シンタックスがお好みなら、 ShouldMatchers や MustMatchers をミックスインすることができます。
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("ユーザーは、要素を stack の先頭から取り出すことができる") {
info("一介のプログラマとして")
info("後入れ先出しの順序でアイテムを管理するために")
info("stack からアイテムを pop で取り出せるようにしたい")
scenario("pop は空でない stack で実行される") {
given("空でない stack")
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
val oldSize = stack.size
when("空でない stack で pop が実行されたとき")
val result = stack.pop()
then("いちばん新しく格納された要素が返されなければならない")
result must be === 2
and("その後、stack は該当する1つのアイテムを減らさなければならない")
stack.size must be === oldSize - 1
}
scenario("pop は空の stack で実行される") {
given("空の stack")
val emptyStack = new Stack[String]
when("pop が stack で実行されたとき")
then("NoSuchElementException が投げられなければならない")
evaluating { emptyStack.pop() } must produce [NoSuchElementException]
and("stack は依然空のままでなければならない")
emptyStack must be ('empty)
}
}
}
ExampleSuite を実行してみましょう。
もう、pending になっているテストはないはずです。
$ scala -cp scalatest-1.5.jar org.scalatest.tools.Runner -p . -o -s
ExampleSpec
Run starting. Expected test count is: 2
ExampleSpec:
Feature: ユーザーは、要素を stack の先頭から取り出すことができる
一介のプログラマとして
後入れ先出しの順序でアイテムを管理するために
stack からアイテムを pop で取り出せるようにしたい
Scenario: pop は空でない stack で実行される
Given 空でない stack
When 空でない stack で pop が実行されたとき
Then いちばん新しく格納された要素が返されなければならない
And その後、stack は該当する1つのアイテムを減らさなければならない
Scenario: pop は空の stack で実行される
Given 空の stack
When pop が stack で実行されたとき
Then NoSuchElementException が投げられなければならない
And stack は依然空のままでなければならない
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.