From 743083181e9b9cc5929d3987cc62558f6d3fcc6c Mon Sep 17 00:00:00 2001 From: gedi Date: Wed, 17 Jun 2015 17:58:22 +0300 Subject: [PATCH] exit status on failure, test godog with godog on travis --- .travis.yml | 5 +++++ cmd/godog/main.go | 6 +++++- suite.go | 52 ++++++++++++++++++++++++++++++++--------------- suite_test.go | 2 ++ utils_test.go | 40 ++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 utils_test.go diff --git a/.travis.yml b/.travis.yml index 523ab9d..ca5cf1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,12 @@ go: - tip script: + # pull all dependencies - go get -t ./... + # run standard go tests - go test -v ./... - go test -race ./... + + # test me with myself + - go run cmd/godog/main.go diff --git a/cmd/godog/main.go b/cmd/godog/main.go index fc076d7..a7214de 100644 --- a/cmd/godog/main.go +++ b/cmd/godog/main.go @@ -16,19 +16,21 @@ func main() { stdout := ansicolor.NewAnsiColorWriter(os.Stdout) builtFile := fmt.Sprintf("%s/%dgodog.go", os.TempDir(), time.Now().UnixNano()) - defer os.Remove(builtFile) // comment out for debug buf, err := godog.Build() if err != nil { + os.Remove(builtFile) panic(err) } w, err := os.Create(builtFile) if err != nil { + os.Remove(builtFile) panic(err) } _, err = w.Write(buf) if err != nil { + os.Remove(builtFile) panic(err) } w.Close() @@ -43,8 +45,10 @@ func main() { err = cmd.Run() switch err.(type) { case *exec.ExitError: + os.Remove(builtFile) os.Exit(1) case *exec.Error: + os.Remove(builtFile) panic(err) } } diff --git a/suite.go b/suite.go index 48f5167..d4f03a6 100644 --- a/suite.go +++ b/suite.go @@ -3,6 +3,7 @@ package godog import ( "flag" "fmt" + "os" "reflect" "regexp" "runtime" @@ -10,6 +11,14 @@ import ( "github.com/DATA-DOG/godog/gherkin" ) +type stepsStatus int + +const ( + stepsStatusPassed stepsStatus = iota + stepsStatusFailed + stepsStatusUndefined +) + type BeforeScenarioHandler interface { BeforeScenario(scenario *gherkin.Scenario) } @@ -66,7 +75,7 @@ type suite struct { features []*gherkin.Feature fmt Formatter - stop bool + failed bool } // New initializes a suite which supports the Suite @@ -122,12 +131,15 @@ func (s *suite) Run() { for _, f := range s.features { s.runFeature(f) - if s.stop { + if s.failed && cfg.stopOnFailure { // stop on first failure break } } s.fmt.Summary() + if s.failed { + os.Exit(1) + } } func (s *suite) runStep(step *gherkin.Step) (err error) { @@ -168,18 +180,21 @@ func (s *suite) runStep(step *gherkin.Step) (err error) { return } -func (s *suite) runSteps(steps []*gherkin.Step) bool { - var failed bool +func (s *suite) runSteps(steps []*gherkin.Step) (st stepsStatus) { for _, step := range steps { - if failed { + if st != stepsStatusPassed { s.fmt.Skipped(step) continue } - if err := s.runStep(step); err != nil { - failed = true + err := s.runStep(step) + switch { + case err == errPending: + st = stepsStatusUndefined + case err != nil: + st = stepsStatusFailed } } - return failed + return } func (s *suite) skipSteps(steps []*gherkin.Step) { @@ -191,7 +206,7 @@ func (s *suite) skipSteps(steps []*gherkin.Step) { func (s *suite) runFeature(f *gherkin.Feature) { s.fmt.Node(f) for _, scenario := range f.Scenarios { - var failed bool + var status stepsStatus // run before scenario handlers for _, h := range s.beforeScenarioHandlers { @@ -201,20 +216,25 @@ func (s *suite) runFeature(f *gherkin.Feature) { // background if f.Background != nil { s.fmt.Node(f.Background) - failed = s.runSteps(f.Background.Steps) + status = s.runSteps(f.Background.Steps) } // scenario s.fmt.Node(scenario) - if failed { + switch { + case status == stepsStatusFailed: s.skipSteps(scenario.Steps) - } else { - failed = s.runSteps(scenario.Steps) + case status == stepsStatusUndefined: + s.skipSteps(scenario.Steps) + default: + status = s.runSteps(scenario.Steps) } - if failed && cfg.stopOnFailure { - s.stop = true - return + if status == stepsStatusFailed { + s.failed = true + if cfg.stopOnFailure { + return + } } } } diff --git a/suite_test.go b/suite_test.go index 113c797..03f7df6 100644 --- a/suite_test.go +++ b/suite_test.go @@ -18,6 +18,8 @@ func (s *suiteFeature) BeforeScenario(scenario *gherkin.Scenario) { cfg.paths = []string{} // reset hook test references s.befScenarioHook = nil + // reset formatter, which collects all details + s.fmt = &testFormatter{} } func (s *suiteFeature) iHaveBeforeScenarioHook(args ...*Arg) error { diff --git a/utils_test.go b/utils_test.go new file mode 100644 index 0000000..ed35954 --- /dev/null +++ b/utils_test.go @@ -0,0 +1,40 @@ +package godog + +import "github.com/DATA-DOG/godog/gherkin" + +type testFormatter struct { + features []*gherkin.Feature + scenarios []*gherkin.Scenario + + failed []*failed + passed []*passed + skipped []*skipped + undefined []*undefined +} + +func (f *testFormatter) Node(node interface{}) { + switch t := node.(type) { + case *gherkin.Feature: + f.features = append(f.features, t) + case *gherkin.Scenario: + f.scenarios = append(f.scenarios, t) + } +} + +func (f *testFormatter) Summary() {} + +func (f *testFormatter) Passed(step *gherkin.Step, match *stepMatchHandler) { + f.passed = append(f.passed, &passed{step}) +} + +func (f *testFormatter) Skipped(step *gherkin.Step) { + f.skipped = append(f.skipped, &skipped{step}) +} + +func (f *testFormatter) Undefined(step *gherkin.Step) { + f.undefined = append(f.undefined, &undefined{step}) +} + +func (f *testFormatter) Failed(step *gherkin.Step, match *stepMatchHandler, err error) { + f.failed = append(f.failed, &failed{step, err}) +}