Specs2を試す(8)

Single step

Given/When/Then の3つのステップは GivenThen で1つにまとめることができる。

import org.specs2._
import specification._

class GivenThenSpec extends Specification { def is =

  "given the name: ${eric}, then the age is ${18}" ! new GivenThen {
    def extract(text: String) = {
      val (name, age) = extract2(text)
      age.toInt must_== 18
    }
  }

}

so オブジェクトを使う手もある。これは GivenThen を作るためのショートカットのようなもの。
次のように定義してある。

// specs2/src/main/scala/org/specs2/specification/RegexStep.scala
object so {
  def apply[R <% Result](f: PartialFunction[Any, R]): GivenThen = new GivenThenFunction(f)
}

apply メソッドが PartialFunction を引数にとって GivenThen を返してくれている。

import org.specs2._
import specification._

class GivenThenSpec extends Specification { def is =

  "given the name: ${eric}, then the age is ${18}" ! so { case (name: String, age: String) =>
    age.toInt must_== 18
  }

}

Conversions

Given/When/Then ステップは型パラメータに対してinvariant(不変)。これは再利用の点で問題になることがある。
例えば Then[X] というステップを定義し、後に X のサブクラスである Y に対し、 Then[Y] を定義したくなったときはどうするか。


以下のコードが意味を成すような場合、implicit conversion を定義してやることでうまく対処できる。*1

  val thenX = new Then[X] {
    def extract(x: X, s: String) = success // x に対してのテスト
  }
  // Y <: X を thenX を Then[Y] ステップとして再利用できる
  val thenY: Then[Y] = thenX

*1:らしいんだけど、ここらへん実例とかが見つからず理解が不十分...