Suppose I have this class:
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)
}
}
I'd like to test the logic in canTransitionTo
(not included here for the sake of simplicity) with scalachecks Commands but I'm having a bit of trouble on how to begin. Any ideas?
There are some tutorials how to test state machines with this framework but they test another property. Usually they create a Command
for each valid transition and fire scalacheck
to do any random combinations of them. The goal of such property is to verify that state machine behaves normally for any number of valid transitions.
This approach will not test canTransitionTo
because it assumes all transitions are valid. Testing transitions between any pair of states will require to reimplement a notion of valid and invalid transitions in terms of scalacheck
. This could be even more complex then original canTransitionTo
function.
If one of transition sets is much smaller than other scalacheck
can help to generate another one. For example if there are only handful of valid transitions and tenth of invalid then generators can help.
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With