some necessary command line options
Этот коммит содержится в:
родитель
cb47b27090
коммит
a3ef3361f8
6 изменённых файлов: 115 добавлений и 16 удалений
15
config.go
15
config.go
|
@ -41,6 +41,11 @@ func init() {
|
|||
|
||||
flag.StringVar(&cfg.format, "format", "pretty", "")
|
||||
flag.StringVar(&cfg.format, "f", "pretty", "")
|
||||
flag.BoolVar(&cfg.definitions, "definitions", false, "")
|
||||
flag.BoolVar(&cfg.definitions, "d", false, "")
|
||||
flag.BoolVar(&cfg.stopOnFailure, "stop-on-failure", false, "")
|
||||
flag.BoolVar(&cfg.version, "version", false, "")
|
||||
|
||||
flag.Usage = func() {
|
||||
// prints an option or argument with a description, or only description
|
||||
opt := func(name, desc string) string {
|
||||
|
@ -66,11 +71,17 @@ func init() {
|
|||
|
||||
// --- OPTIONS ---
|
||||
fmt.Println(cl("Options:", yellow))
|
||||
// --> step definitions
|
||||
fmt.Println(opt("-d, --definitions", "Print all available step definitions."))
|
||||
// --> format
|
||||
fmt.Println(opt("-f, --format=pretty", "How to format tests output. Available formats:"))
|
||||
for _, f := range formatters {
|
||||
fmt.Println(opt("", s(4)+"- "+cl(f.name, yellow)+": "+f.description))
|
||||
}
|
||||
// --> stop on failure
|
||||
fmt.Println(opt("--stop-on-failure", "Stop processing on first failed scenario."))
|
||||
// --> version
|
||||
fmt.Println(opt("--version", "Show current "+cl("godog", yellow)+" version."))
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +89,10 @@ func init() {
|
|||
type config struct {
|
||||
paths []string
|
||||
format string
|
||||
|
||||
definitions bool
|
||||
stopOnFailure bool
|
||||
version bool
|
||||
}
|
||||
|
||||
func (c *config) validate() error {
|
||||
|
|
|
@ -6,4 +6,12 @@ Feature: suite hooks
|
|||
Background:
|
||||
Given I have a before scenario hook
|
||||
And a feature path "features/load_features.feature:6"
|
||||
# When I parse and run features
|
||||
And I parse features
|
||||
|
||||
Scenario: hi there
|
||||
When I run features
|
||||
Then I should have a scenario "" recorded in the hook
|
||||
|
||||
Scenario: and there
|
||||
When I run features
|
||||
Then I should have a scenario "" recorded in the hook
|
||||
|
|
40
formatter.go
40
formatter.go
|
@ -89,10 +89,16 @@ func (f *pretty) line(tok *gherkin.Token) string {
|
|||
|
||||
// checks whether it should not print a background step once again
|
||||
func (f *pretty) canPrintStep(step *gherkin.Step) bool {
|
||||
if f.background != nil {
|
||||
return step.Background != nil
|
||||
if f.background == nil {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
|
||||
if step.Background == nil {
|
||||
f.doneBackground = true
|
||||
return true
|
||||
}
|
||||
|
||||
return !f.doneBackground
|
||||
}
|
||||
|
||||
// Node takes a gherkin node for formatting
|
||||
|
@ -110,9 +116,20 @@ func (f *pretty) Node(node interface{}) {
|
|||
fmt.Println(bcl("Feature: ", white) + t.Title)
|
||||
fmt.Println(t.Description)
|
||||
case *gherkin.Background:
|
||||
f.background = t
|
||||
fmt.Println("\n" + bcl("Background:", white))
|
||||
// determine comment position based on step length
|
||||
f.commentPos = len(t.Token.Text)
|
||||
for _, step := range t.Steps {
|
||||
if len(step.Token.Text) > f.commentPos {
|
||||
f.commentPos = len(step.Token.Text)
|
||||
}
|
||||
}
|
||||
// do not repeat background
|
||||
if !f.doneBackground {
|
||||
f.background = t
|
||||
fmt.Println("\n" + strings.Repeat(" ", t.Token.Indent) + bcl("Background:", white))
|
||||
}
|
||||
case *gherkin.Scenario:
|
||||
// determine comment position based on step length
|
||||
f.commentPos = len(t.Token.Text)
|
||||
for _, step := range t.Steps {
|
||||
if len(step.Token.Text) > f.commentPos {
|
||||
|
@ -187,9 +204,6 @@ func (f *pretty) Summary() {
|
|||
|
||||
// prints a single matched step
|
||||
func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c color) {
|
||||
if !f.canPrintStep(step) {
|
||||
return
|
||||
}
|
||||
var text string
|
||||
if m := (match.expr.FindStringSubmatchIndex(step.Text))[2:]; len(m) > 0 {
|
||||
var pos, i int
|
||||
|
@ -228,7 +242,9 @@ func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c
|
|||
|
||||
// Passed is called to represent a passed step
|
||||
func (f *pretty) Passed(step *gherkin.Step, match *stepMatchHandler) {
|
||||
f.printMatchedStep(step, match, green)
|
||||
if f.canPrintStep(step) {
|
||||
f.printMatchedStep(step, match, green)
|
||||
}
|
||||
f.passed = append(f.passed, &passed{step})
|
||||
}
|
||||
|
||||
|
@ -250,7 +266,9 @@ func (f *pretty) Undefined(step *gherkin.Step) {
|
|||
|
||||
// Failed is called to represent a failed step
|
||||
func (f *pretty) Failed(step *gherkin.Step, match *stepMatchHandler, err error) {
|
||||
f.printMatchedStep(step, match, red)
|
||||
fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red))
|
||||
if f.canPrintStep(step) {
|
||||
f.printMatchedStep(step, match, red)
|
||||
fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red))
|
||||
}
|
||||
f.failed = append(f.failed, &failed{step, err})
|
||||
}
|
||||
|
|
2
godog.go
2
godog.go
|
@ -33,3 +33,5 @@ As you’ll see, Godog is easy to learn, quick to use, and will put the fun back
|
|||
Godog was inspired by Behat and the above description is taken from it's documentation.
|
||||
*/
|
||||
package godog
|
||||
|
||||
const Version = "v0.1.0-alpha"
|
||||
|
|
50
suite.go
50
suite.go
|
@ -3,7 +3,9 @@ package godog
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
)
|
||||
|
@ -63,6 +65,8 @@ type suite struct {
|
|||
stepHandlers []*stepMatchHandler
|
||||
features []*gherkin.Feature
|
||||
fmt Formatter
|
||||
|
||||
stop bool
|
||||
}
|
||||
|
||||
// New initializes a suite which supports the Suite
|
||||
|
@ -99,14 +103,29 @@ func (s *suite) Run() {
|
|||
if !flag.Parsed() {
|
||||
flag.Parse()
|
||||
}
|
||||
fatal(cfg.validate())
|
||||
|
||||
// check if we need to just show something first
|
||||
switch {
|
||||
case cfg.version:
|
||||
fmt.Println(cl("Godog", green) + " version is " + cl(Version, yellow))
|
||||
return
|
||||
case cfg.definitions:
|
||||
s.printStepDefinitions()
|
||||
return
|
||||
}
|
||||
|
||||
// run a feature suite
|
||||
fatal(cfg.validate())
|
||||
s.fmt = cfg.formatter()
|
||||
s.features, err = cfg.features()
|
||||
fatal(err)
|
||||
|
||||
for _, f := range s.features {
|
||||
s.runFeature(f)
|
||||
if s.stop {
|
||||
// stop on first failure
|
||||
break
|
||||
}
|
||||
}
|
||||
s.fmt.Summary()
|
||||
}
|
||||
|
@ -171,14 +190,16 @@ func (s *suite) skipSteps(steps []*gherkin.Step) {
|
|||
|
||||
func (s *suite) runFeature(f *gherkin.Feature) {
|
||||
s.fmt.Node(f)
|
||||
var failed bool
|
||||
for _, scenario := range f.Scenarios {
|
||||
var failed bool
|
||||
|
||||
// run before scenario handlers
|
||||
for _, h := range s.beforeScenarioHandlers {
|
||||
h.BeforeScenario(scenario)
|
||||
}
|
||||
|
||||
// background
|
||||
if f.Background != nil && !failed {
|
||||
if f.Background != nil {
|
||||
s.fmt.Node(f.Background)
|
||||
failed = s.runSteps(f.Background.Steps)
|
||||
}
|
||||
|
@ -188,7 +209,28 @@ func (s *suite) runFeature(f *gherkin.Feature) {
|
|||
if failed {
|
||||
s.skipSteps(scenario.Steps)
|
||||
} else {
|
||||
s.runSteps(scenario.Steps)
|
||||
failed = s.runSteps(scenario.Steps)
|
||||
}
|
||||
|
||||
if failed && cfg.stopOnFailure {
|
||||
s.stop = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (st *suite) printStepDefinitions() {
|
||||
var longest int
|
||||
for _, def := range st.stepHandlers {
|
||||
if longest < len(def.expr.String()) {
|
||||
longest = len(def.expr.String())
|
||||
}
|
||||
}
|
||||
for _, def := range st.stepHandlers {
|
||||
location := runtime.FuncForPC(reflect.ValueOf(def.handler).Pointer()).Name()
|
||||
fmt.Println(cl(def.expr.String(), yellow)+s(longest-len(def.expr.String())), cl("# "+location, black))
|
||||
}
|
||||
if len(st.stepHandlers) == 0 {
|
||||
fmt.Println("there were no contexts registered, could not find any step definition..")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,22 @@ import (
|
|||
|
||||
type suiteFeature struct {
|
||||
suite
|
||||
// for hook tests
|
||||
befScenarioHook *gherkin.Scenario
|
||||
}
|
||||
|
||||
func (s *suiteFeature) BeforeScenario(scenario *gherkin.Scenario) {
|
||||
// reset feature paths
|
||||
cfg.paths = []string{}
|
||||
// reset hook test references
|
||||
s.befScenarioHook = nil
|
||||
}
|
||||
|
||||
func (s *suiteFeature) iHaveBeforeScenarioHook(args ...*Arg) error {
|
||||
s.suite.BeforeScenario(BeforeScenarioHandlerFunc(func(scenario *gherkin.Scenario) {
|
||||
s.befScenarioHook = scenario
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *suiteFeature) featurePath(args ...*Arg) error {
|
||||
|
@ -63,4 +74,7 @@ func SuiteContext(g Suite) {
|
|||
g.Step(
|
||||
regexp.MustCompile(`^I should have ([\d]+) scenarios? registered$`),
|
||||
StepHandlerFunc(s.numScenariosRegistered))
|
||||
g.Step(
|
||||
regexp.MustCompile(`^I have a before scenario hook$`),
|
||||
StepHandlerFunc(s.iHaveBeforeScenarioHook))
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче