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.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

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

@ -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

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