diff --git a/flags.go b/flags.go index ed052c3..a839a5f 100644 --- a/flags.go +++ b/flags.go @@ -46,6 +46,8 @@ func FlagSet(opt *Options) *flag.FlagSet { set.BoolVar(&opt.ShowStepDefinitions, "d", false, "Print all available step definitions.") set.BoolVar(&opt.StopOnFailure, "stop-on-failure", false, "Stop processing on first failed scenario.") set.BoolVar(&opt.NoColors, "no-colors", false, "Disable ansi colors.") + set.BoolVar(&opt.Randomize, "random", false, "Randomize scenario execution order.") + set.Int64Var(&opt.RandomSeed, "seed", 0, "Specify random seed to reproduce shuffling from a previous run.\n(implies --random)") set.Usage = usage(set, opt.Output) return set } @@ -64,7 +66,14 @@ func (f *flagged) name() string { case len(f.short) > 0: name = fmt.Sprintf("-%s", f.short) } - if f.dflt != "true" && f.dflt != "false" { + + if f.long == "seed" { + // `seed`` is special in that we will later assign it randomly + // if the user specifies `--random` without specifying one, + // so mask the "default" value here to avoid UI confusion about + // what the value will end up being. + name += "=SEED" + } else if f.dflt != "true" && f.dflt != "false" { name += "=" + f.dflt } return name diff --git a/options.go b/options.go index a1235ee..b1d9625 100644 --- a/options.go +++ b/options.go @@ -13,16 +13,22 @@ type Options struct { // Print step definitions found and exit ShowStepDefinitions bool - // RandomSeed, if not `0`, will be used to run scenarios in a random order. + // Randomize causes scenarios to be run in random order. // // Randomizing scenario order is especially helpful for detecting // situations where you have state leaking between scenarios, which can // cause flickering or fragile tests. + Randomize bool + + // RandomSeed allows specifying the seed to reproduce the random scenario + // shuffling from a previous run. // - // The default value of `0` means "do not randomize". + // When `RandomSeed` is left at the nil value (`0`), but `Randomize` + // has been set to `true`, then godog will automatically pick a random + // seed between `1-99999` for ease of specification. // - // The magic value of `-1` means "pick a random seed for me", the resulting - // seed will only be between `1-99999` for ease of specification. + // If RandomSeed is set to anything other than the default nil value (`0`), + // then `Randomize = true` will be implied. RandomSeed int64 // Stops on the first failure diff --git a/run.go b/run.go index 7d2351c..a20fd34 100644 --- a/run.go +++ b/run.go @@ -111,10 +111,14 @@ func RunWithOptions(suite string, contextInitializer func(suite *Suite), opt Opt features, err := parseFeatures(opt.Tags, opt.Paths) fatal(err) - seed := opt.RandomSeed - if seed == -1 { - // if RandomSeed opt is -1, means pick a memorable rand seed as default - // the docStrings for Option specify this should be 1-99999 (same as ruby Cucumber) + // the actual seed value which will be propogated + // if left as nil value, then scenarios run sequentially + var seed int64 + // use specified seed if exists, or assign one ourselves if + // none specified but user wants randomization + if opt.RandomSeed != 0 { + seed = opt.RandomSeed + } else if opt.Randomize && opt.RandomSeed == 0 { r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) seed = r.Int63n(99998) + 1 }