single randomSeed Option value, handled as flag.Value
Best of both worlds, this allows for a single int64 value in the Options struct, but at the same time we can do `—random` from command line with no args and have a default value Chosen.
Этот коммит содержится в:
родитель
f50c3b5e14
коммит
d2eb563953
3 изменённых файлов: 66 добавлений и 30 удалений
13
flags.go
13
flags.go
|
@ -26,6 +26,10 @@ var descTagsOption = "Filter scenarios by tags. Expression can be:\n" +
|
||||||
s(4) + "- " + colors.Yellow(`"@wip && ~@new"`) + ": run wip scenarios, but exclude new\n" +
|
s(4) + "- " + colors.Yellow(`"@wip && ~@new"`) + ": run wip scenarios, but exclude new\n" +
|
||||||
s(4) + "- " + colors.Yellow(`"@wip,@undone"`) + ": run wip or undone scenarios"
|
s(4) + "- " + colors.Yellow(`"@wip,@undone"`) + ": run wip or undone scenarios"
|
||||||
|
|
||||||
|
var descRandomOption = "Randomly shuffle the scenario execution order.\n" +
|
||||||
|
"Specify SEED to reproduce the shuffling from a previous run.\n" +
|
||||||
|
s(4) + `e.g. ` + colors.Yellow(`--random`) + " or " + colors.Yellow(`--random=5738`)
|
||||||
|
|
||||||
// FlagSet allows to manage flags by external suite runner
|
// FlagSet allows to manage flags by external suite runner
|
||||||
func FlagSet(opt *Options) *flag.FlagSet {
|
func FlagSet(opt *Options) *flag.FlagSet {
|
||||||
descFormatOption := "How to format tests output. Available formats:\n"
|
descFormatOption := "How to format tests output. Available formats:\n"
|
||||||
|
@ -46,8 +50,7 @@ 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.Var(&opt.Randomize, "random", descRandomOption)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -67,12 +70,12 @@ func (f *flagged) name() string {
|
||||||
name = fmt.Sprintf("-%s", f.short)
|
name = fmt.Sprintf("-%s", f.short)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.long == "seed" {
|
if f.long == "random" {
|
||||||
// `seed`` is special in that we will later assign it randomly
|
// `random` is special in that we will later assign it randomly
|
||||||
// if the user specifies `--random` without specifying one,
|
// if the user specifies `--random` without specifying one,
|
||||||
// so mask the "default" value here to avoid UI confusion about
|
// so mask the "default" value here to avoid UI confusion about
|
||||||
// what the value will end up being.
|
// what the value will end up being.
|
||||||
name += "=SEED"
|
name += "[=SEED]"
|
||||||
} else if f.dflt != "true" && f.dflt != "false" {
|
} else if f.dflt != "true" && f.dflt != "false" {
|
||||||
name += "=" + f.dflt
|
name += "=" + f.dflt
|
||||||
}
|
}
|
||||||
|
|
65
options.go
65
options.go
|
@ -1,6 +1,11 @@
|
||||||
package godog
|
package godog
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Options are suite run options
|
// Options are suite run options
|
||||||
// flags are mapped to these options.
|
// flags are mapped to these options.
|
||||||
|
@ -13,23 +18,22 @@ type Options struct {
|
||||||
// Print step definitions found and exit
|
// Print step definitions found and exit
|
||||||
ShowStepDefinitions bool
|
ShowStepDefinitions bool
|
||||||
|
|
||||||
// Randomize causes scenarios to be run in random order.
|
// Randomize, if not `0`, will be used to run scenarios in a 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.
|
|
||||||
//
|
//
|
||||||
// When `RandomSeed` is left at the nil value (`0`), but `Randomize`
|
// The default value of `0` means "do not randomize".
|
||||||
// has been set to `true`, then godog will automatically pick a random
|
|
||||||
// seed between `1-99999` for ease of specification.
|
|
||||||
//
|
//
|
||||||
// If RandomSeed is set to anything other than the default nil value (`0`),
|
// The magic value of `-1` means "pick a random seed for me", and godog will
|
||||||
// then `Randomize = true` will be implied.
|
// assign a seed on it's own during the `RunWithOptions` phase, similar to if
|
||||||
RandomSeed int64
|
// you specified `--random` on the command line.
|
||||||
|
//
|
||||||
|
// Any other value will be used as the random seed for shuffling. Re-using the
|
||||||
|
// same seed will allow you to reproduce the shuffle order of a previous run
|
||||||
|
// to isolate an error condition.
|
||||||
|
Randomize randomSeed
|
||||||
|
|
||||||
// Stops on the first failure
|
// Stops on the first failure
|
||||||
StopOnFailure bool
|
StopOnFailure bool
|
||||||
|
@ -53,3 +57,40 @@ type Options struct {
|
||||||
// Where it should print formatter output
|
// Where it should print formatter output
|
||||||
Output io.Writer
|
Output io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// randomSeed implements `flag.Value`, see https://golang.org/pkg/flag/#Value
|
||||||
|
type randomSeed int64
|
||||||
|
|
||||||
|
// Choose randomly assigns a convenient pseudo-random seed value.
|
||||||
|
// The resulting seed will be between `1-99999` for later ease of specification.
|
||||||
|
func (rs *randomSeed) Choose() {
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
|
||||||
|
*rs = randomSeed(r.Int63n(99998) + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *randomSeed) Set(s string) error {
|
||||||
|
if s == "true" {
|
||||||
|
rs.Choose()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if s == "false" {
|
||||||
|
*rs = 0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
i, err := strconv.ParseInt(s, 10, 64)
|
||||||
|
*rs = randomSeed(i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs randomSeed) String() string {
|
||||||
|
return strconv.FormatInt(int64(rs), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a Value has an IsBoolFlag() bool method returning true, the command-line
|
||||||
|
// parser makes -name equivalent to -name=true rather than using the next
|
||||||
|
// command-line argument.
|
||||||
|
func (rs *randomSeed) IsBoolFlag() bool {
|
||||||
|
return *rs == 0
|
||||||
|
}
|
||||||
|
|
18
run.go
18
run.go
|
@ -3,9 +3,7 @@ package godog
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/DATA-DOG/godog/colors"
|
"github.com/DATA-DOG/godog/colors"
|
||||||
)
|
)
|
||||||
|
@ -111,23 +109,17 @@ 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)
|
||||||
|
|
||||||
// the actual seed value which will be propogated
|
// handle convenience condition where user specified `-1` in Options struct,
|
||||||
// if left as nil value, then scenarios run sequentially
|
// asking us to choose the random value seed for them.
|
||||||
var seed int64
|
if opt.Randomize == -1 {
|
||||||
// use specified seed if exists, or assign one ourselves if
|
opt.Randomize.Choose()
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r := runner{
|
r := runner{
|
||||||
fmt: formatter(suite, output),
|
fmt: formatter(suite, output),
|
||||||
initializer: contextInitializer,
|
initializer: contextInitializer,
|
||||||
features: features,
|
features: features,
|
||||||
randomSeed: seed,
|
randomSeed: int64(opt.Randomize),
|
||||||
stopOnFailure: opt.StopOnFailure,
|
stopOnFailure: opt.StopOnFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче