2016-06-01 43 views
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) 
    } 
} 

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

回答

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