When writing test for state machines, I came across a need for a helper that would all call flow into a path some percentage% of times.
Eg:
func TestSelfDrivingCar_BasicRun(t *testing.T) { car := NewMockCar(t) car.Start() if (/* 50% probability that this will happen */) { car.SimulateLidarFailure() } else if /* 25% probability that this will happen */ { car.SimulateVisionFailure() } else { /* 25% probability that this will happen*/ car.SimulateGearBoxFailure() } car.VerifySafeTrajectory() }
You can write a small Go helper like this:
package testutils import ( "math/rand" "time" ) // Odds returns True to pct% number of Check() calls type Odds interface { Check() bool } // odds returns `true` pct% of times type odds struct { randgen *rand.Rand pct int } // NewOdds returns a odds instance with the given percent vaule func NewOdds(pct int) Odds { src := rand.NewSource(time.Now().UnixNano()) return &odds{ randgen: rand.New(src), pct: pct, } } // Check returns True to pct% of Check() calls func (o *odds) Check() bool { return o.randgen.Intn(100) < o.pct }
Usage:
func TestSelfDrivingCar_BasicRun(t *testing.T) { odds50pct, odds25pct := NewOdds(50), NewOdds(25) car := NewMockCar(t) car.Start() if odds50pct.Check() { car.SimulateLidarFailure() } else if odds25pct.Check() { car.SimulateVisionFailure() } else { /* 25% probability that this will happen*/ car.SimulateGearBoxFailure() } car.VerifySafeTrajectory() }
ps: No, I don’t work on self-driving cars – this is just a code sample 🙂