【问题标题】:Test valid state transitions with scalacheck使用 scalacheck 测试有效的状态转换
【发布时间】:2016-09-30 05:16:35
【问题描述】:
假设我有这个类:
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 中的逻辑(为了简单起见,这里不包括在内),但我在如何开始时遇到了一些麻烦。有什么想法吗?
【问题讨论】:
标签:
scala
state-machine
scalacheck
property-based-testing
【解决方案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)
}