2016-06-01 17 views
5

Angenommen, ich habe diese Klasse:-Test gültig Zustandsübergänge mit 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) 
    } 
} 

Ich möchte die Logik in canTransitionTo (hier nicht aus Gründen der Einfachheit enthalten) testen, mit scalachecks Befehle aber ich habe ein bisschen Schwierigkeiten beim Start. Irgendwelche Ideen?

Antwort

1

Es gibt some tutorials, wie Zustandsautomaten mit diesem Framework getestet werden, aber sie testen eine andere Eigenschaft. Normalerweise erstellen sie einen Command für jeden gültigen Übergang und feuern scalacheck, um beliebige zufällige Kombinationen von ihnen zu tun. Das Ziel einer solchen Eigenschaft besteht darin, zu verifizieren, dass sich die Zustandsmaschine für eine beliebige Anzahl gültiger Übergänge normal verhält.

Dieser Ansatz testet canTransitionTo nicht, da angenommen wird, dass alle Übergänge gültig sind. Das Testen von Übergängen zwischen einem beliebigen Paar von Zuständen erfordert eine Neuimplementierung eines Begriffs gültiger und ungültiger Übergänge in Bezug auf scalacheck. Dies könnte noch komplexer als die ursprüngliche canTransitionTo Funktion sein.


Wenn eines der Übergangssätze viel kleiner als andere ist scalacheck kann ein anderes generieren helfen. Zum Beispiel, wenn es nur eine Handvoll gültiger Übergänge und ein Zehntel von ungültigen gibt, dann können Generatoren helfen.

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