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