do not fire events when feature or scenario is empty
Этот коммит содержится в:
родитель
df188464c6
коммит
272624afcc
4 изменённых файлов: 131 добавлений и 12 удалений
|
@ -51,3 +51,50 @@ Feature: suite events
|
||||||
| AfterFeature | 2 |
|
| AfterFeature | 2 |
|
||||||
| AfterSuite | 1 |
|
| AfterSuite | 1 |
|
||||||
|
|
||||||
|
Scenario: should not trigger events on empty feature
|
||||||
|
Given a feature "normal.feature" file:
|
||||||
|
"""
|
||||||
|
Feature: empty
|
||||||
|
|
||||||
|
Scenario: one
|
||||||
|
|
||||||
|
Scenario: two
|
||||||
|
"""
|
||||||
|
When I run feature suite
|
||||||
|
Then these events had to be fired for a number of times:
|
||||||
|
| BeforeSuite | 1 |
|
||||||
|
| BeforeFeature | 0 |
|
||||||
|
| BeforeScenario | 0 |
|
||||||
|
| BeforeStep | 0 |
|
||||||
|
| AfterStep | 0 |
|
||||||
|
| AfterScenario | 0 |
|
||||||
|
| AfterFeature | 0 |
|
||||||
|
| AfterSuite | 1 |
|
||||||
|
|
||||||
|
Scenario: should not trigger events on empty scenarios
|
||||||
|
Given a feature "normal.feature" file:
|
||||||
|
"""
|
||||||
|
Feature: half empty
|
||||||
|
|
||||||
|
Scenario: one
|
||||||
|
|
||||||
|
Scenario: two
|
||||||
|
Then passing step
|
||||||
|
|
||||||
|
Scenario Outline: three
|
||||||
|
Then passing step
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| a |
|
||||||
|
| 1 |
|
||||||
|
"""
|
||||||
|
When I run feature suite
|
||||||
|
Then these events had to be fired for a number of times:
|
||||||
|
| BeforeSuite | 1 |
|
||||||
|
| BeforeFeature | 1 |
|
||||||
|
| BeforeScenario | 2 |
|
||||||
|
| BeforeStep | 2 |
|
||||||
|
| AfterStep | 2 |
|
||||||
|
| AfterScenario | 2 |
|
||||||
|
| AfterFeature | 1 |
|
||||||
|
| AfterSuite | 1 |
|
||||||
|
|
|
@ -89,6 +89,9 @@ func (f *pretty) Node(node interface{}) {
|
||||||
f.outline = nil
|
f.outline = nil
|
||||||
f.steps = len(t.Steps) + f.totalBgSteps
|
f.steps = len(t.Steps) + f.totalBgSteps
|
||||||
f.scenarioKeyword = false
|
f.scenarioKeyword = false
|
||||||
|
if isEmptyScenario(t) {
|
||||||
|
f.printUndefinedScenario(t)
|
||||||
|
}
|
||||||
case *gherkin.ScenarioOutline:
|
case *gherkin.ScenarioOutline:
|
||||||
f.outline = t
|
f.outline = t
|
||||||
f.scenario = nil
|
f.scenario = nil
|
||||||
|
@ -100,6 +103,21 @@ func (f *pretty) Node(node interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *pretty) printUndefinedScenario(sc *gherkin.Scenario) {
|
||||||
|
if f.bgSteps > 0 {
|
||||||
|
f.commentPos = f.longestStep(f.feature.Background.Steps, f.length(f.feature.Background))
|
||||||
|
fmt.Fprintln(f.out, "\n"+s(f.indent)+whiteb(f.feature.Background.Keyword+": "+f.feature.Background.Name))
|
||||||
|
|
||||||
|
for _, step := range f.feature.Background.Steps {
|
||||||
|
f.bgSteps--
|
||||||
|
f.printStep(step, nil, colors.Cyan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text := s(f.indent) + whiteb(f.scenario.Keyword+": ") + sc.Name
|
||||||
|
text += s(f.commentPos-f.length(f.scenario)+1) + f.line(sc.Location)
|
||||||
|
fmt.Fprintln(f.out, "\n"+text)
|
||||||
|
}
|
||||||
|
|
||||||
// Summary sumarize the feature formatter output
|
// Summary sumarize the feature formatter output
|
||||||
func (f *pretty) Summary() {
|
func (f *pretty) Summary() {
|
||||||
// failed steps on background are not scenarios
|
// failed steps on background are not scenarios
|
||||||
|
@ -284,6 +302,7 @@ func (f *pretty) printStepKind(res *stepResult) {
|
||||||
if f.outline != nil {
|
if f.outline != nil {
|
||||||
f.outlineSteps = append(f.outlineSteps, res)
|
f.outlineSteps = append(f.outlineSteps, res)
|
||||||
}
|
}
|
||||||
|
var bgStep bool
|
||||||
|
|
||||||
// if has not printed background yet
|
// if has not printed background yet
|
||||||
switch {
|
switch {
|
||||||
|
@ -292,9 +311,11 @@ func (f *pretty) printStepKind(res *stepResult) {
|
||||||
f.commentPos = f.longestStep(f.feature.Background.Steps, f.length(f.feature.Background))
|
f.commentPos = f.longestStep(f.feature.Background.Steps, f.length(f.feature.Background))
|
||||||
fmt.Fprintln(f.out, "\n"+s(f.indent)+whiteb(f.feature.Background.Keyword+": "+f.feature.Background.Name))
|
fmt.Fprintln(f.out, "\n"+s(f.indent)+whiteb(f.feature.Background.Keyword+": "+f.feature.Background.Name))
|
||||||
f.bgSteps--
|
f.bgSteps--
|
||||||
|
bgStep = true
|
||||||
// subsequent background steps
|
// subsequent background steps
|
||||||
case f.bgSteps > 0:
|
case f.bgSteps > 0:
|
||||||
f.bgSteps--
|
f.bgSteps--
|
||||||
|
bgStep = true
|
||||||
// first step of scenario, print header and calculate comment position
|
// first step of scenario, print header and calculate comment position
|
||||||
case f.scenario != nil:
|
case f.scenario != nil:
|
||||||
// print scenario keyword and value if first example
|
// print scenario keyword and value if first example
|
||||||
|
@ -333,7 +354,9 @@ func (f *pretty) printStepKind(res *stepResult) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.printStep(res.step, res.def, res.typ.clr())
|
if !f.isBackgroundStep(res.step) || bgStep {
|
||||||
|
f.printStep(res.step, res.def, res.typ.clr())
|
||||||
|
}
|
||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
fmt.Fprintln(f.out, s(f.indent*2)+redb(fmt.Sprintf("%+v", res.err)))
|
fmt.Fprintln(f.out, s(f.indent*2)+redb(fmt.Sprintf("%+v", res.err)))
|
||||||
}
|
}
|
||||||
|
@ -342,6 +365,19 @@ func (f *pretty) printStepKind(res *stepResult) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *pretty) isBackgroundStep(step *gherkin.Step) bool {
|
||||||
|
if f.feature.Background == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bstep := range f.feature.Background.Steps {
|
||||||
|
if bstep.Location.Line == step.Location.Line {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// print table with aligned table cells
|
// print table with aligned table cells
|
||||||
func (f *pretty) printTable(t *gherkin.DataTable, c colors.ColorFunc) {
|
func (f *pretty) printTable(t *gherkin.DataTable, c colors.ColorFunc) {
|
||||||
var l = longest(t, c)
|
var l = longest(t, c)
|
||||||
|
|
25
gherkin.go
25
gherkin.go
|
@ -9,3 +9,28 @@ func examples(ex interface{}) (*gherkin.Examples, bool) {
|
||||||
t, ok := ex.(*gherkin.Examples)
|
t, ok := ex.(*gherkin.Examples)
|
||||||
return t, ok
|
return t, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// means there are no scenarios or they do not have steps
|
||||||
|
func isEmptyFeature(ft *gherkin.Feature) bool {
|
||||||
|
for _, def := range ft.ScenarioDefinitions {
|
||||||
|
if !isEmptyScenario(def) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// means scenario dooes not have steps
|
||||||
|
func isEmptyScenario(def interface{}) bool {
|
||||||
|
switch t := def.(type) {
|
||||||
|
case *gherkin.Scenario:
|
||||||
|
if len(t.Steps) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case *gherkin.ScenarioOutline:
|
||||||
|
if len(t.Steps) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
33
suite.go
33
suite.go
|
@ -425,8 +425,10 @@ func (s *Suite) runOutline(outline *gherkin.ScenarioOutline, b *gherkin.Backgrou
|
||||||
groups := example.TableBody
|
groups := example.TableBody
|
||||||
|
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
for _, f := range s.beforeScenarioHandlers {
|
if !isEmptyScenario(outline) {
|
||||||
f(outline)
|
for _, f := range s.beforeScenarioHandlers {
|
||||||
|
f(outline)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var steps []*gherkin.Step
|
var steps []*gherkin.Step
|
||||||
for _, outlineStep := range outline.Steps {
|
for _, outlineStep := range outline.Steps {
|
||||||
|
@ -493,8 +495,10 @@ func (s *Suite) runOutline(outline *gherkin.ScenarioOutline, b *gherkin.Backgrou
|
||||||
|
|
||||||
err := s.runSteps(steps)
|
err := s.runSteps(steps)
|
||||||
|
|
||||||
for _, f := range s.afterScenarioHandlers {
|
if !isEmptyScenario(outline) {
|
||||||
f(outline, err)
|
for _, f := range s.afterScenarioHandlers {
|
||||||
|
f(outline, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.shouldFail(err) {
|
if s.shouldFail(err) {
|
||||||
|
@ -521,8 +525,10 @@ func (s *Suite) shouldFail(err error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) runFeature(f *feature) {
|
func (s *Suite) runFeature(f *feature) {
|
||||||
for _, fn := range s.beforeFeatureHandlers {
|
if !isEmptyFeature(f.Feature) {
|
||||||
fn(f.Feature)
|
for _, fn := range s.beforeFeatureHandlers {
|
||||||
|
fn(f.Feature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fmt.Feature(f.Feature, f.Path, f.Content)
|
s.fmt.Feature(f.Feature, f.Path, f.Content)
|
||||||
|
@ -541,8 +547,10 @@ func (s *Suite) runFeature(f *feature) {
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
for _, fn := range s.afterFeatureHandlers {
|
if !isEmptyFeature(f.Feature) {
|
||||||
fn(f.Feature)
|
for _, fn := range s.afterFeatureHandlers {
|
||||||
|
fn(f.Feature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -567,6 +575,11 @@ func (s *Suite) runFeature(f *feature) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) runScenario(scenario *gherkin.Scenario, b *gherkin.Background) (err error) {
|
func (s *Suite) runScenario(scenario *gherkin.Scenario, b *gherkin.Background) (err error) {
|
||||||
|
if isEmptyScenario(scenario) {
|
||||||
|
s.fmt.Node(scenario)
|
||||||
|
return ErrUndefined
|
||||||
|
}
|
||||||
|
|
||||||
// run before scenario handlers
|
// run before scenario handlers
|
||||||
for _, f := range s.beforeScenarioHandlers {
|
for _, f := range s.beforeScenarioHandlers {
|
||||||
f(scenario)
|
f(scenario)
|
||||||
|
@ -704,9 +717,7 @@ func filterFeatures(tags string, collected map[string]*feature) (features []*fea
|
||||||
ft.ScenarioDefinitions = scenarios
|
ft.ScenarioDefinitions = scenarios
|
||||||
applyTagFilter(tags, ft.Feature)
|
applyTagFilter(tags, ft.Feature)
|
||||||
|
|
||||||
if len(ft.ScenarioDefinitions) > 0 {
|
features = append(features, ft)
|
||||||
features = append(features, ft)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(sortByOrderGiven(features))
|
sort.Sort(sortByOrderGiven(features))
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче