adds more tests for multistep execution
Этот коммит содержится в:
родитель
703b40de76
коммит
5bfd57218a
5 изменённых файлов: 158 добавлений и 27 удалений
|
@ -14,7 +14,7 @@ Feature: event stream formatter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: should process simple scenario
|
Scenario: should process simple scenario
|
||||||
Given a feature path "features/load.feature:22"
|
Given a feature path "features/load.feature:23"
|
||||||
When I run feature suite with formatter "events"
|
When I run feature suite with formatter "events"
|
||||||
Then the following events should be fired:
|
Then the following events should be fired:
|
||||||
"""
|
"""
|
||||||
|
@ -35,7 +35,7 @@ Feature: event stream formatter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: should process outline scenario
|
Scenario: should process outline scenario
|
||||||
Given a feature path "features/load.feature:30"
|
Given a feature path "features/load.feature:31"
|
||||||
When I run feature suite with formatter "events"
|
When I run feature suite with formatter "events"
|
||||||
Then the following events should be fired:
|
Then the following events should be fired:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -34,7 +34,6 @@ func TestProgressFormatterOutput(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// var zeroDuration time.Duration
|
|
||||||
expected := `
|
expected := `
|
||||||
...F-.P-.UU.....F..P..U 23
|
...F-.P-.UU.....F..P..U 23
|
||||||
|
|
||||||
|
@ -88,3 +87,113 @@ func trimAllLines(s string) string {
|
||||||
}
|
}
|
||||||
return strings.Join(lines, "\n")
|
return strings.Join(lines, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var basicGherkinFeature = `
|
||||||
|
Feature: basic
|
||||||
|
|
||||||
|
Scenario: passing scenario
|
||||||
|
When step1
|
||||||
|
Then step2
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestProgressFormatterWhenStepPanics(t *testing.T) {
|
||||||
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := colors.Uncolored(&buf)
|
||||||
|
r := runner{
|
||||||
|
fmt: progressFunc("progress", w),
|
||||||
|
features: []*feature{&feature{Feature: feat}},
|
||||||
|
initializer: func(s *Suite) {
|
||||||
|
s.Step(`^step1$`, func() error { return nil })
|
||||||
|
s.Step(`^step2$`, func() error { panic("omg") })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.run() {
|
||||||
|
t.Fatal("the suite should have failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
out := buf.String()
|
||||||
|
if idx := strings.Index(out, "github.com/DATA-DOG/godog/fmt_progress_test.go:116"); idx == -1 {
|
||||||
|
t.Fatal("expected to find panic stacktrace")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProgressFormatterWithPassingMultisteps(t *testing.T) {
|
||||||
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := colors.Uncolored(&buf)
|
||||||
|
r := runner{
|
||||||
|
fmt: progressFunc("progress", w),
|
||||||
|
features: []*feature{&feature{Feature: feat}},
|
||||||
|
initializer: func(s *Suite) {
|
||||||
|
s.Step(`^sub1$`, func() error { return nil })
|
||||||
|
s.Step(`^sub-sub$`, func() error { return nil })
|
||||||
|
s.Step(`^sub2$`, func() Steps { return Steps{"sub-sub", "sub1", "step1"} })
|
||||||
|
s.Step(`^step1$`, func() error { return nil })
|
||||||
|
s.Step(`^step2$`, func() Steps { return Steps{"sub1", "sub2"} })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.run() {
|
||||||
|
t.Fatal("the suite should have passed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProgressFormatterWithFailingMultisteps(t *testing.T) {
|
||||||
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := colors.Uncolored(&buf)
|
||||||
|
r := runner{
|
||||||
|
fmt: progressFunc("progress", w),
|
||||||
|
features: []*feature{&feature{Feature: feat}},
|
||||||
|
initializer: func(s *Suite) {
|
||||||
|
s.Step(`^sub1$`, func() error { return nil })
|
||||||
|
s.Step(`^sub-sub$`, func() error { return fmt.Errorf("errored") })
|
||||||
|
s.Step(`^sub2$`, func() Steps { return Steps{"sub-sub", "sub1", "step1"} })
|
||||||
|
s.Step(`^step1$`, func() error { return nil })
|
||||||
|
s.Step(`^step2$`, func() Steps { return Steps{"sub1", "sub2"} })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.run() {
|
||||||
|
t.Fatal("the suite should have failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProgressFormatterWithPanicInMultistep(t *testing.T) {
|
||||||
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := colors.Uncolored(&buf)
|
||||||
|
r := runner{
|
||||||
|
fmt: progressFunc("progress", w),
|
||||||
|
features: []*feature{&feature{Feature: feat}},
|
||||||
|
initializer: func(s *Suite) {
|
||||||
|
s.Step(`^sub1$`, func() error { return nil })
|
||||||
|
s.Step(`^sub-sub$`, func() error { return nil })
|
||||||
|
s.Step(`^sub2$`, func() []string { return []string{"sub-sub", "sub1", "step1"} })
|
||||||
|
s.Step(`^step1$`, func() error { return nil })
|
||||||
|
s.Step(`^step2$`, func() []string { return []string{"sub1", "sub2"} })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.run() {
|
||||||
|
t.Fatal("the suite should have failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
run.go
2
run.go
|
@ -54,7 +54,7 @@ func (r *runner) concurrent(rate int) (failed bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) run() (failed bool) {
|
func (r *runner) run() bool {
|
||||||
suite := &Suite{
|
suite := &Suite{
|
||||||
fmt: r.fmt,
|
fmt: r.fmt,
|
||||||
randomSeed: r.randomSeed,
|
randomSeed: r.randomSeed,
|
||||||
|
|
45
suite.go
45
suite.go
|
@ -211,18 +211,7 @@ func (s *Suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
||||||
match := s.matchStep(step)
|
match := s.matchStep(step)
|
||||||
s.fmt.Defined(step, match)
|
s.fmt.Defined(step, match)
|
||||||
|
|
||||||
// @TODO custom undefined err here to pass step text for snippet
|
// user multistep definitions may panic
|
||||||
// @TODO user multistep definitions may panic
|
|
||||||
if s.maybeUndefined(match) {
|
|
||||||
s.fmt.Undefined(step)
|
|
||||||
return ErrUndefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if prevStepErr != nil {
|
|
||||||
s.fmt.Skipped(step)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = &traceError{
|
err = &traceError{
|
||||||
|
@ -230,6 +219,15 @@ func (s *Suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
||||||
stack: callStack(),
|
stack: callStack(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prevStepErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == ErrUndefined {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
s.fmt.Passed(step, match)
|
s.fmt.Passed(step, match)
|
||||||
|
@ -245,6 +243,17 @@ func (s *Suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// @TODO custom undefined err here to pass step text for snippet
|
||||||
|
if s.maybeUndefined(match) {
|
||||||
|
s.fmt.Undefined(step)
|
||||||
|
return ErrUndefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if prevStepErr != nil {
|
||||||
|
s.fmt.Skipped(step)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// run before step handlers
|
// run before step handlers
|
||||||
for _, f := range s.beforeStepHandlers {
|
for _, f := range s.beforeStepHandlers {
|
||||||
f(step)
|
f(step)
|
||||||
|
@ -303,9 +312,15 @@ func (s *Suite) matchStepText(text string) *StepDef {
|
||||||
args = append(args, m)
|
args = append(args, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO copy step def
|
// since we need to assign arguments
|
||||||
h.args = args
|
// better to copy the step definition
|
||||||
return h
|
return &StepDef{
|
||||||
|
args: args,
|
||||||
|
hv: h.hv,
|
||||||
|
Expr: h.Expr,
|
||||||
|
Handler: h.Handler,
|
||||||
|
nested: h.nested,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -20,21 +20,28 @@ func TestMain(m *testing.M) {
|
||||||
format := "progress" // non verbose mode
|
format := "progress" // non verbose mode
|
||||||
concurrency := 4
|
concurrency := 4
|
||||||
|
|
||||||
|
var specific bool
|
||||||
for _, arg := range os.Args[1:] {
|
for _, arg := range os.Args[1:] {
|
||||||
if arg == "-test.v=true" { // go test transforms -v option - verbose mode
|
if arg == "-test.v=true" { // go test transforms -v option - verbose mode
|
||||||
format = "pretty"
|
format = "pretty"
|
||||||
concurrency = 1
|
concurrency = 1
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if strings.Index(arg, "-test.run") == 0 {
|
||||||
|
specific = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var status int
|
||||||
|
if !specific {
|
||||||
|
status = RunWithOptions("godog", func(s *Suite) {
|
||||||
|
SuiteContext(s)
|
||||||
|
}, Options{
|
||||||
|
Format: format, // pretty format for verbose mode, otherwise - progress
|
||||||
|
Paths: []string{"features"},
|
||||||
|
Concurrency: concurrency, // concurrency for verbose mode is 1
|
||||||
|
Randomize: time.Now().UnixNano(), // randomize scenario execution order
|
||||||
|
})
|
||||||
}
|
}
|
||||||
status := RunWithOptions("godog", func(s *Suite) {
|
|
||||||
SuiteContext(s)
|
|
||||||
}, Options{
|
|
||||||
Format: format, // pretty format for verbose mode, otherwise - progress
|
|
||||||
Paths: []string{"features"},
|
|
||||||
Concurrency: concurrency, // concurrency for verbose mode is 1
|
|
||||||
Randomize: time.Now().UnixNano(), // randomize scenario execution order
|
|
||||||
})
|
|
||||||
|
|
||||||
if st := m.Run(); st > status {
|
if st := m.Run(); st > status {
|
||||||
status = st
|
status = st
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче