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 // Print step definitions found and exit
ShowStepDefinitions bool 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 // Randomizing scenario order is especially helpful for detecting
// where you have state leaking between scenarios, which // situations where you have state leaking between scenarios, which can
// can cause flickering or fragile tests. // cause flickering or fragile tests.
RandomOrder bool //
// 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 // Stops on the first failure
StopOnFailure bool StopOnFailure bool

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

@ -13,7 +13,7 @@ import (
type initializer func(*Suite) type initializer func(*Suite)
type runner struct { type runner struct {
randomOrder bool randomSeed int64
stopOnFailure bool stopOnFailure bool
features []*feature features []*feature
fmt Formatter fmt Formatter
@ -33,7 +33,7 @@ func (r *runner) concurrent(rate int) (failed bool) {
} }
suite := &Suite{ suite := &Suite{
fmt: r.fmt, fmt: r.fmt,
randomOrder: r.randomOrder, randomSeed: r.randomSeed,
stopOnFailure: r.stopOnFailure, stopOnFailure: r.stopOnFailure,
features: []*feature{feat}, features: []*feature{feat},
} }
@ -58,7 +58,7 @@ func (r *runner) concurrent(rate int) (failed bool) {
func (r *runner) run() (failed bool) { func (r *runner) run() (failed bool) {
suite := &Suite{ suite := &Suite{
fmt: r.fmt, fmt: r.fmt,
randomOrder: r.randomOrder, randomSeed: r.randomSeed,
stopOnFailure: r.stopOnFailure, stopOnFailure: r.stopOnFailure,
features: r.features, features: r.features,
} }
@ -111,20 +111,26 @@ 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
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{ r := runner{
fmt: formatter(suite, output), fmt: formatter(suite, output),
initializer: contextInitializer, initializer: contextInitializer,
features: features, features: features,
randomOrder: opt.RandomOrder, randomSeed: seed,
stopOnFailure: opt.StopOnFailure, 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 var failed bool
if opt.Concurrency > 1 { if opt.Concurrency > 1 {
failed = r.concurrent(opt.Concurrency) failed = r.concurrent(opt.Concurrency)

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

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