switch Random opt from bool to int64

This allows for us to propagate the seed value around, and not have to
have two different values in Options when we want to allow
specification of seed.  It does introduce some “magic values”, but the
document them in the Options struct docstrings.
Этот коммит содержится в:
Matthew Rothenberg 2017-04-25 11:42:40 -04:00
родитель 4a754b26a5
коммит 0eed963c63
3 изменённых файлов: 28 добавлений и 17 удалений

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

@ -13,12 +13,17 @@ type Options struct {
// Print step definitions found and exit
ShowStepDefinitions bool
// Run scenarios in random order.
// RandomSeed, if not `0`, will be used to run scenarios in a random order.
//
// This is especially helpful for detecting situations
// where you have state leaking between scenarios, which
// can cause flickering or fragile tests.
RandomOrder bool
// Randomizing scenario order is especially helpful for detecting
// situations where you have state leaking between scenarios, which can
// cause flickering or fragile tests.
//
// The default value of `0` means "do not randomize".
//
// 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.
RandomSeed int64
// Stops on the first failure
StopOnFailure bool

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

@ -13,7 +13,7 @@ import (
type initializer func(*Suite)
type runner struct {
randomOrder bool
randomSeed int64
stopOnFailure bool
features []*feature
fmt Formatter
@ -33,7 +33,7 @@ func (r *runner) concurrent(rate int) (failed bool) {
}
suite := &Suite{
fmt: r.fmt,
randomOrder: r.randomOrder,
randomSeed: r.randomSeed,
stopOnFailure: r.stopOnFailure,
features: []*feature{feat},
}
@ -58,7 +58,7 @@ func (r *runner) concurrent(rate int) (failed bool) {
func (r *runner) run() (failed bool) {
suite := &Suite{
fmt: r.fmt,
randomOrder: r.randomOrder,
randomSeed: r.randomSeed,
stopOnFailure: r.stopOnFailure,
features: r.features,
}
@ -111,20 +111,26 @@ 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)
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
seed = r.Int63n(99998) + 1
}
if seed != 0 {
// init global rand module (concurrent safe) with our seed
rand.Seed(seed)
}
r := runner{
fmt: formatter(suite, output),
initializer: contextInitializer,
features: features,
randomOrder: opt.RandomOrder,
randomSeed: seed,
stopOnFailure: opt.StopOnFailure,
}
if opt.RandomOrder {
// TODO(mroth): allow for seed to be specified in options,
// and print it at the end of a run for replication purposes
rand.Seed(time.Now().UTC().UnixNano())
}
var failed bool
if opt.Concurrency > 1 {
failed = r.concurrent(opt.Concurrency)

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

@ -50,7 +50,7 @@ type Suite struct {
fmt Formatter
failed bool
randomOrder bool
randomSeed int64
stopOnFailure bool
// suite event handlers
@ -336,7 +336,7 @@ func (s *Suite) runFeature(f *feature) {
// make a local copy of the feature scenario defenitions,
// then shuffle it if we are randomizing scenarios
scenarios := make([]interface{}, len(f.ScenarioDefinitions))
if s.randomOrder {
if s.randomSeed != 0 {
perm := rand.Perm(len(f.ScenarioDefinitions))
for i, v := range perm {
scenarios[v] = f.ScenarioDefinitions[i]