2016-06-01 12 views
5

Załóżmy, że mam tej klasy:testowe ważne przemiany państwowe z scalacheck

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

Chciałbym przetestować logikę w canTransitionTo (nie wchodzi tu dla uproszczenia) z scalachecks Commands ale mam trochę kłopotu, od czego zacząć. Jakieś pomysły?

Odpowiedz

1

Istnieje some tutorials sposób testowania automatów stanów z tym szkieletem, ale testują one inną właściwość. Zwykle tworzy się Command dla każdego prawidłowego przejścia i strzela scalacheck, aby wykonać dowolne losowe kombinacje. Celem takiej właściwości jest sprawdzenie, czy automat stanów zachowuje się normalnie dla dowolnej liczby prawidłowych przejść.

To podejście nie będzie testować canTransitionTo, ponieważ zakłada, że ​​wszystkie przejścia są prawidłowe. Testowanie przejść między dowolnymi parami stanów wymaga ponownego wdrożenia pojęcia poprawnych i nieprawidłowych przejść pod kątem scalacheck. Może to być nawet bardziej złożone niż oryginalna funkcja canTransitionTo.


Jeśli jeden z zestawów przejściowych jest o wiele mniejszy niż inne scalacheck może przyczynić się do wygenerowania kolejnego. Na przykład, jeśli jest tylko garść poprawnych przejść i dziesiąta część nieważna, generatory mogą pomóc.

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