5

このクラスがあるとします:

case class Receipt(id: Long, state: String) {
  def transitionTo(newState: String) = {
    if (!canTransitionTo(newState)) {
       throw new IllegalStateExcetion(s"cant transition from $state to $newState")
    }
    this.copy(state = newState)
  }
}

canTransitionToscalachecks コマンドを使用して (簡単にするためにここには含まれていません)ロジックをテストしたいのですが、開始方法に少し問題があります。何か案は?

4

1 に答える 1

1

このフレームワークでステート マシンをテストする方法のチュートリアルがいくつかありますが、それらは別のプロパティをテストします。通常、それらはCommand有効な遷移ごとに forを作成し、scalacheckそれらのランダムな組み合わせを実行するために起動します。このようなプロパティの目的は、ステート マシンが任意の数の有効な遷移に対して正常に動作することを確認することです。

canTransitionToこのアプローチは、すべての遷移が有効であると想定しているため、テストしません。状態の任意のペア間の遷移をテストするには、 に関して有効な遷移と無効な遷移の概念を再実装する必要がありますscalacheck。これは、元の関数よりもさらに複雑になる可能性がありcanTransitionToます。


トランジション セットの 1 つが他よりはるかに小さい場合は、別のトランジション セットscalacheckを生成するのに役立ちます。たとえば、有効な遷移がほんの一握りで、無効な遷移が 10 分の 1 しかない場合は、ジェネレーターが役立ちます。

private val allStates: Gen[String] = Gen.oneOf("State1", "State2", "State3")

private val validTransitions: Set[(String, String)] = Set("State1" -> "State2", "State2" -> "State3", "State3" -> "State1")
private val validTransitionsGen: Gen[(String, String)] = Gen.oneOf(validTransitions.toSeq)

private val invalidTransition: Gen[(String, String)] = for {
  from <- allStates
  to <- allStates
  if !validTransitions.contains(from -> to) //this is reimplementaion of canTransitionTo
} yield from -> to

property("valid transitions") = forAll(validTransitionsGen) { transition =>
  Receipt(0, transition._1).canTransitionTo(transition._2)
}

property("invalid transitions") = forAll(invalidTransition) { transition =>
  !Receipt(0, transition._1).canTransitionTo(transition._2)
}
于 2016-07-31T01:17:46.543 に答える