Skip to content

Commit

Permalink
Pretty Print when using rules (#440) (#480)
Browse files Browse the repository at this point in the history
* Pretty Print when using rules (#440)

* Pretty Print when using rules (#440)

* fix a few formatting mistakes (#440)

* added test with rule and scenario outline (#440)
  • Loading branch information
dumpsterfireproject committed Jun 17, 2022
1 parent c5a86a4 commit 5d705e5
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 19 deletions.
99 changes: 99 additions & 0 deletions features/formatter/pretty.feature
Expand Up @@ -449,3 +449,102 @@ Feature: pretty formatter
16 steps (16 passed)
0s
"""

Scenario: Support of Feature Plus Rule
Given a feature "features/simple.feature" file:
"""
Feature: simple feature with a rule
simple feature description
Rule: simple rule
simple rule description
Example: simple scenario
simple scenario description
Given passing step
"""
When I run feature suite with formatter "pretty"
Then the rendered output will be as follows:
"""
Feature: simple feature with a rule
simple feature description
Example: simple scenario # features/simple.feature:5
Given passing step # suite_context.go:0 -> SuiteContext.func2
1 scenarios (1 passed)
1 steps (1 passed)
0s
"""

Scenario: Support of Feature Plus Rule with Background
Given a feature "features/simple.feature" file:
"""
Feature: simple feature with a rule with Background
simple feature description
Rule: simple rule
simple rule description
Background:
Given passing step
Example: simple scenario
simple scenario description
Given passing step
"""
When I run feature suite with formatter "pretty"
Then the rendered output will be as follows:
"""
Feature: simple feature with a rule with Background
simple feature description
Background:
Given passing step # suite_context.go:0 -> SuiteContext.func2
Example: simple scenario # features/simple.feature:7
Given passing step # suite_context.go:0 -> SuiteContext.func2
1 scenarios (1 passed)
2 steps (2 passed)
0s
"""

Scenario: Support of Feature Plus Rule with Scenario Outline
Given a feature "features/simple.feature" file:
"""
Feature: simple feature with a rule with Scenario Outline
simple feature description
Rule: simple rule
simple rule description
Scenario Outline: simple scenario
simple scenario description
Given <status> step
Examples: simple examples
| status |
| passing |
| failing |
"""
When I run feature suite with formatter "pretty"
Then the rendered output will be as follows:
"""
Feature: simple feature with a rule with Scenario Outline
simple feature description
Scenario Outline: simple scenario # features/simple.feature:5
Given <status> step # suite_context.go:0 -> SuiteContext.func2
Examples: simple examples
| status |
| passing |
| failing |
intentional failure
--- Failed steps:
Scenario Outline: simple scenario # features/simple.feature:5
Given failing step # features/simple.feature:8
Error: intentional failure
2 scenarios (1 passed, 1 failed)
2 steps (1 passed, 1 failed)
0s
"""
26 changes: 25 additions & 1 deletion internal/formatters/fmt_pretty.go
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/models"
)

func init() {
Expand Down Expand Up @@ -350,15 +351,38 @@ func (f *Pretty) printTableHeader(row *messages.TableRow, max []int) {
f.printTableRow(row, max, cyan)
}

func isFirstScenarioInRule(rule *messages.Rule, scenario *messages.Scenario) bool {
if rule == nil || scenario == nil {
return false
}
var firstScenario *messages.Scenario
for _, c := range rule.Children {
if c.Scenario != nil {
firstScenario = c.Scenario
break
}
}
return firstScenario != nil && firstScenario.Id == scenario.Id
}

func isFirstPickleAndNoRule(feature *models.Feature, pickle *messages.Pickle, rule *messages.Rule) bool {
if rule != nil {
return false
}
return feature.Pickles[0].Id == pickle.Id
}

func (f *Pretty) printStep(pickle *messages.Pickle, pickleStep *messages.PickleStep) {
feature := f.Storage.MustGetFeature(pickle.Uri)
astBackground := feature.FindBackground(pickle.AstNodeIds[0])
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
astRule := feature.FindRule(pickle.AstNodeIds[0])
astStep := feature.FindStep(pickleStep.AstNodeIds[0])

var astBackgroundStep bool
var firstExecutedBackgroundStep bool
var backgroundSteps int

if astBackground != nil {
backgroundSteps = len(astBackground.Steps)

Expand All @@ -371,7 +395,7 @@ func (f *Pretty) printStep(pickle *messages.Pickle, pickleStep *messages.PickleS
}
}

firstPickle := feature.Pickles[0].Id == pickle.Id
firstPickle := isFirstPickleAndNoRule(feature, pickle, astRule) || isFirstScenarioInRule(astRule, astScenario)

if astBackgroundStep && !firstPickle {
return
Expand Down
@@ -0,0 +1,30 @@
Feature: rules with examples with backgrounds

Rule: first rule

Background: for first rule
Given passing step
And passing step

Example: rule 1 example 1
When passing step
Then passing step

Example: rule 1 example 2
When passing step
Then passing step


Rule: second rule

Background: for second rule
Given passing step
And passing step

Example: rule 1 example 1
When passing step
Then passing step

Example: rule 2 example 2
When passing step
Then passing step
@@ -0,0 +1,29 @@
<bold-white>Feature:</bold-white> rules with examples with backgrounds

<bold-white>Background:</bold-white> for first rule
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:9</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Example:</bold-white> rule 1 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:13</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Background:</bold-white> for second rule
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:24</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Example:</bold-white> rule 2 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:28</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

4 scenarios (<green>4 passed</green>)
16 steps (<green>16 passed</green>)
0s
71 changes: 70 additions & 1 deletion internal/models/feature.go
Expand Up @@ -13,12 +13,35 @@ type Feature struct {
Content []byte
}

// FindScenario ...
// FindRule returns the rule to which the given scenario belongs
func (f Feature) FindRule(astScenarioID string) *messages.Rule {
for _, child := range f.GherkinDocument.Feature.Children {
if ru := child.Rule; ru != nil {
if rc := child.Rule; rc != nil {
for _, rcc := range rc.Children {
if sc := rcc.Scenario; sc != nil && sc.Id == astScenarioID {
return ru
}
}
}
}
}
return nil
}

// FindScenario returns the scenario in the feature or in a rule in the feature
func (f Feature) FindScenario(astScenarioID string) *messages.Scenario {
for _, child := range f.GherkinDocument.Feature.Children {
if sc := child.Scenario; sc != nil && sc.Id == astScenarioID {
return sc
}
if rc := child.Rule; rc != nil {
for _, rcc := range rc.Children {
if sc := rcc.Scenario; sc != nil && sc.Id == astScenarioID {
return sc
}
}
}
}

return nil
Expand All @@ -36,6 +59,18 @@ func (f Feature) FindBackground(astScenarioID string) *messages.Background {
if sc := child.Scenario; sc != nil && sc.Id == astScenarioID {
return bg
}

if ru := child.Rule; ru != nil {
for _, rc := range ru.Children {
if tmp := rc.Background; tmp != nil {
bg = tmp
}

if sc := rc.Scenario; sc != nil && sc.Id == astScenarioID {
return bg
}
}
}
}

return nil
Expand All @@ -53,6 +88,19 @@ func (f Feature) FindExample(exampleAstID string) (*messages.Examples, *messages
}
}
}
if ru := child.Rule; ru != nil {
for _, rc := range ru.Children {
if sc := rc.Scenario; sc != nil {
for _, example := range sc.Examples {
for _, row := range example.TableBody {
if row.Id == exampleAstID {
return example, row
}
}
}
}
}
}
}

return nil, nil
Expand All @@ -61,6 +109,27 @@ func (f Feature) FindExample(exampleAstID string) (*messages.Examples, *messages
// FindStep ...
func (f Feature) FindStep(astStepID string) *messages.Step {
for _, child := range f.GherkinDocument.Feature.Children {

if ru := child.Rule; ru != nil {
for _, ch := range ru.Children {
if sc := ch.Scenario; sc != nil {
for _, step := range sc.Steps {
if step.Id == astStepID {
return step
}
}
}

if bg := ch.Background; bg != nil {
for _, step := range bg.Steps {
if step.Id == astStepID {
return step
}
}
}
}
}

if sc := child.Scenario; sc != nil {
for _, step := range sc.Steps {
if step.Id == astStepID {
Expand Down

0 comments on commit 5d705e5

Please sign in to comment.