使用scalacheck测试有效的状态转换

时间:2016-06-01 02:29:46

标签: scala state-machine scalacheck property-based-testing

假设我有这门课程:

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)
  }
}

我想用scalachecks命令测试canTransitionTo中的逻辑(这里不包括为了简单起见),但我对如何开始有点麻烦。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

some tutorials如何使用此框架测试状态机,但他们测试另一个属性。通常,他们会为每个有效转换创建Command,并触发scalacheck来对其进行随机组合。此属性的目标是验证状态机对于任意数量的有效转换是否正常运行。

此方法不会测试canTransitionTo,因为它假定所有转换都有效。测试任何一对状态之间的转换将需要重新实现scalacheck方面的有效和无效转换的概念。这可能比原始canTransitionTo函数更复杂。

如果其中一个转换集比其他scalacheck小得多,则可以帮助生成另一个转换集。例如,如果只有少数有效转换和十分之一无效,那么生成器可以提供帮助。

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)
}