allow setting randomization via flags

allows for setting randomization with flags, but also modifies the
Options struct to now have two separate values

Overall this relates in a much more understandable UI from a user
perspective, since the normal case for randomization will be a user
just saying “run these out of order please” — and in a rare case they
may wish to additionally supply a seed to try to reproduce an older run
to trigger the same error condition.
Этот коммит содержится в:
Matthew Rothenberg 2017-04-25 14:50:58 -04:00
родитель cf6160b3f2
коммит f50c3b5e14
3 изменённых файлов: 28 добавлений и 9 удалений

Просмотреть файл

@ -46,6 +46,8 @@ func FlagSet(opt *Options) *flag.FlagSet {
set.BoolVar(&opt.ShowStepDefinitions, "d", false, "Print all available step definitions.") 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.StopOnFailure, "stop-on-failure", false, "Stop processing on first failed scenario.")
set.BoolVar(&opt.NoColors, "no-colors", false, "Disable ansi colors.") 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) set.Usage = usage(set, opt.Output)
return set return set
} }
@ -64,7 +66,14 @@ func (f *flagged) name() string {
case len(f.short) > 0: case len(f.short) > 0:
name = fmt.Sprintf("-%s", f.short) 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 name += "=" + f.dflt
} }
return name return name

Просмотреть файл

@ -13,16 +13,22 @@ type Options struct {
// Print step definitions found and exit // Print step definitions found and exit
ShowStepDefinitions bool 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 // Randomizing scenario order is especially helpful for detecting
// situations where you have state leaking between scenarios, which can // situations where you have state leaking between scenarios, which can
// cause flickering or fragile tests. // 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 // If RandomSeed is set to anything other than the default nil value (`0`),
// seed will only be between `1-99999` for ease of specification. // then `Randomize = true` will be implied.
RandomSeed int64 RandomSeed int64
// Stops on the first failure // Stops on the first failure

12
run.go
Просмотреть файл

@ -111,10 +111,14 @@ func RunWithOptions(suite string, contextInitializer func(suite *Suite), opt Opt
features, err := parseFeatures(opt.Tags, opt.Paths) features, err := parseFeatures(opt.Tags, opt.Paths)
fatal(err) fatal(err)
seed := opt.RandomSeed // the actual seed value which will be propogated
if seed == -1 { // if left as nil value, then scenarios run sequentially
// if RandomSeed opt is -1, means pick a memorable rand seed as default var seed int64
// the docStrings for Option specify this should be 1-99999 (same as ruby Cucumber) // 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())) r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
seed = r.Int63n(99998) + 1 seed = r.Int63n(99998) + 1
} }