Skip to content

Commit 5d705e5

Browse files
Pretty Print when using rules (cucumber#440) (cucumber#480)
* Pretty Print when using rules (cucumber#440) * Pretty Print when using rules (cucumber#440) * fix a few formatting mistakes (cucumber#440) * added test with rule and scenario outline (cucumber#440)
1 parent c5a86a4 commit 5d705e5

File tree

8 files changed

+368
-19
lines changed

8 files changed

+368
-19
lines changed

features/formatter/pretty.feature

+99
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,102 @@ Feature: pretty formatter
449449
16 steps (16 passed)
450450
0s
451451
"""
452+
453+
Scenario: Support of Feature Plus Rule
454+
Given a feature "features/simple.feature" file:
455+
"""
456+
Feature: simple feature with a rule
457+
simple feature description
458+
Rule: simple rule
459+
simple rule description
460+
Example: simple scenario
461+
simple scenario description
462+
Given passing step
463+
"""
464+
When I run feature suite with formatter "pretty"
465+
Then the rendered output will be as follows:
466+
"""
467+
Feature: simple feature with a rule
468+
simple feature description
469+
470+
Example: simple scenario # features/simple.feature:5
471+
Given passing step # suite_context.go:0 -> SuiteContext.func2
472+
473+
1 scenarios (1 passed)
474+
1 steps (1 passed)
475+
0s
476+
"""
477+
478+
Scenario: Support of Feature Plus Rule with Background
479+
Given a feature "features/simple.feature" file:
480+
"""
481+
Feature: simple feature with a rule with Background
482+
simple feature description
483+
Rule: simple rule
484+
simple rule description
485+
Background:
486+
Given passing step
487+
Example: simple scenario
488+
simple scenario description
489+
Given passing step
490+
"""
491+
When I run feature suite with formatter "pretty"
492+
Then the rendered output will be as follows:
493+
"""
494+
Feature: simple feature with a rule with Background
495+
simple feature description
496+
497+
Background:
498+
Given passing step # suite_context.go:0 -> SuiteContext.func2
499+
500+
Example: simple scenario # features/simple.feature:7
501+
Given passing step # suite_context.go:0 -> SuiteContext.func2
502+
503+
1 scenarios (1 passed)
504+
2 steps (2 passed)
505+
0s
506+
"""
507+
508+
Scenario: Support of Feature Plus Rule with Scenario Outline
509+
Given a feature "features/simple.feature" file:
510+
"""
511+
Feature: simple feature with a rule with Scenario Outline
512+
simple feature description
513+
Rule: simple rule
514+
simple rule description
515+
Scenario Outline: simple scenario
516+
simple scenario description
517+
518+
Given <status> step
519+
520+
Examples: simple examples
521+
| status |
522+
| passing |
523+
| failing |
524+
"""
525+
When I run feature suite with formatter "pretty"
526+
Then the rendered output will be as follows:
527+
"""
528+
Feature: simple feature with a rule with Scenario Outline
529+
simple feature description
530+
531+
Scenario Outline: simple scenario # features/simple.feature:5
532+
Given <status> step # suite_context.go:0 -> SuiteContext.func2
533+
534+
Examples: simple examples
535+
| status |
536+
| passing |
537+
| failing |
538+
intentional failure
539+
540+
--- Failed steps:
541+
542+
Scenario Outline: simple scenario # features/simple.feature:5
543+
Given failing step # features/simple.feature:8
544+
Error: intentional failure
545+
546+
547+
2 scenarios (1 passed, 1 failed)
548+
2 steps (1 passed, 1 failed)
549+
0s
550+
"""

internal/formatters/fmt_pretty.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/cucumber/godog/colors"
1414
"github.com/cucumber/godog/formatters"
15+
"github.com/cucumber/godog/internal/models"
1516
)
1617

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

354+
func isFirstScenarioInRule(rule *messages.Rule, scenario *messages.Scenario) bool {
355+
if rule == nil || scenario == nil {
356+
return false
357+
}
358+
var firstScenario *messages.Scenario
359+
for _, c := range rule.Children {
360+
if c.Scenario != nil {
361+
firstScenario = c.Scenario
362+
break
363+
}
364+
}
365+
return firstScenario != nil && firstScenario.Id == scenario.Id
366+
}
367+
368+
func isFirstPickleAndNoRule(feature *models.Feature, pickle *messages.Pickle, rule *messages.Rule) bool {
369+
if rule != nil {
370+
return false
371+
}
372+
return feature.Pickles[0].Id == pickle.Id
373+
}
374+
353375
func (f *Pretty) printStep(pickle *messages.Pickle, pickleStep *messages.PickleStep) {
354376
feature := f.Storage.MustGetFeature(pickle.Uri)
355377
astBackground := feature.FindBackground(pickle.AstNodeIds[0])
356378
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
379+
astRule := feature.FindRule(pickle.AstNodeIds[0])
357380
astStep := feature.FindStep(pickleStep.AstNodeIds[0])
358381

359382
var astBackgroundStep bool
360383
var firstExecutedBackgroundStep bool
361384
var backgroundSteps int
385+
362386
if astBackground != nil {
363387
backgroundSteps = len(astBackground.Steps)
364388

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

374-
firstPickle := feature.Pickles[0].Id == pickle.Id
398+
firstPickle := isFirstPickleAndNoRule(feature, pickle, astRule) || isFirstScenarioInRule(astRule, astScenario)
375399

376400
if astBackgroundStep && !firstPickle {
377401
return
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Feature: rules with examples with backgrounds
2+
3+
Rule: first rule
4+
5+
Background: for first rule
6+
Given passing step
7+
And passing step
8+
9+
Example: rule 1 example 1
10+
When passing step
11+
Then passing step
12+
13+
Example: rule 1 example 2
14+
When passing step
15+
Then passing step
16+
17+
18+
Rule: second rule
19+
20+
Background: for second rule
21+
Given passing step
22+
And passing step
23+
24+
Example: rule 1 example 1
25+
When passing step
26+
Then passing step
27+
28+
Example: rule 2 example 2
29+
When passing step
30+
Then passing step
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<bold-white>Feature:</bold-white> rules with examples with backgrounds
2+
3+
<bold-white>Background:</bold-white> for first rule
4+
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
5+
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
6+
7+
<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:9</bold-black>
8+
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
9+
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
10+
11+
<bold-white>Example:</bold-white> rule 1 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:13</bold-black>
12+
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
13+
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
14+
15+
<bold-white>Background:</bold-white> for second rule
16+
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
17+
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
18+
19+
<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:24</bold-black>
20+
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
21+
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
22+
23+
<bold-white>Example:</bold-white> rule 2 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:28</bold-black>
24+
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
25+
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
26+
27+
4 scenarios (<green>4 passed</green>)
28+
16 steps (<green>16 passed</green>)
29+
0s

internal/models/feature.go

+70-1
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,35 @@ type Feature struct {
1313
Content []byte
1414
}
1515

16-
// FindScenario ...
16+
// FindRule returns the rule to which the given scenario belongs
17+
func (f Feature) FindRule(astScenarioID string) *messages.Rule {
18+
for _, child := range f.GherkinDocument.Feature.Children {
19+
if ru := child.Rule; ru != nil {
20+
if rc := child.Rule; rc != nil {
21+
for _, rcc := range rc.Children {
22+
if sc := rcc.Scenario; sc != nil && sc.Id == astScenarioID {
23+
return ru
24+
}
25+
}
26+
}
27+
}
28+
}
29+
return nil
30+
}
31+
32+
// FindScenario returns the scenario in the feature or in a rule in the feature
1733
func (f Feature) FindScenario(astScenarioID string) *messages.Scenario {
1834
for _, child := range f.GherkinDocument.Feature.Children {
1935
if sc := child.Scenario; sc != nil && sc.Id == astScenarioID {
2036
return sc
2137
}
38+
if rc := child.Rule; rc != nil {
39+
for _, rcc := range rc.Children {
40+
if sc := rcc.Scenario; sc != nil && sc.Id == astScenarioID {
41+
return sc
42+
}
43+
}
44+
}
2245
}
2346

2447
return nil
@@ -36,6 +59,18 @@ func (f Feature) FindBackground(astScenarioID string) *messages.Background {
3659
if sc := child.Scenario; sc != nil && sc.Id == astScenarioID {
3760
return bg
3861
}
62+
63+
if ru := child.Rule; ru != nil {
64+
for _, rc := range ru.Children {
65+
if tmp := rc.Background; tmp != nil {
66+
bg = tmp
67+
}
68+
69+
if sc := rc.Scenario; sc != nil && sc.Id == astScenarioID {
70+
return bg
71+
}
72+
}
73+
}
3974
}
4075

4176
return nil
@@ -53,6 +88,19 @@ func (f Feature) FindExample(exampleAstID string) (*messages.Examples, *messages
5388
}
5489
}
5590
}
91+
if ru := child.Rule; ru != nil {
92+
for _, rc := range ru.Children {
93+
if sc := rc.Scenario; sc != nil {
94+
for _, example := range sc.Examples {
95+
for _, row := range example.TableBody {
96+
if row.Id == exampleAstID {
97+
return example, row
98+
}
99+
}
100+
}
101+
}
102+
}
103+
}
56104
}
57105

58106
return nil, nil
@@ -61,6 +109,27 @@ func (f Feature) FindExample(exampleAstID string) (*messages.Examples, *messages
61109
// FindStep ...
62110
func (f Feature) FindStep(astStepID string) *messages.Step {
63111
for _, child := range f.GherkinDocument.Feature.Children {
112+
113+
if ru := child.Rule; ru != nil {
114+
for _, ch := range ru.Children {
115+
if sc := ch.Scenario; sc != nil {
116+
for _, step := range sc.Steps {
117+
if step.Id == astStepID {
118+
return step
119+
}
120+
}
121+
}
122+
123+
if bg := ch.Background; bg != nil {
124+
for _, step := range bg.Steps {
125+
if step.Id == astStepID {
126+
return step
127+
}
128+
}
129+
}
130+
}
131+
}
132+
64133
if sc := child.Scenario; sc != nil {
65134
for _, step := range sc.Steps {
66135
if step.Id == astStepID {

0 commit comments

Comments
 (0)