diff --git a/fmt.go b/fmt.go
index 476708c..5a92fbf 100644
--- a/fmt.go
+++ b/fmt.go
@@ -306,16 +306,21 @@ func (f *basefmt) Summary() {
switch t := def.(type) {
case *gherkin.Scenario:
total++
+ if len(t.Steps) == 0 {
+ undefined++
+ }
case *gherkin.ScenarioOutline:
for _, ex := range t.Examples {
if examples, hasExamples := examples(ex); hasExamples {
total += len(examples.TableBody)
+ if len(t.Steps) == 0 {
+ undefined += len(examples.TableBody)
+ }
}
}
}
}
}
- passed = total
var owner interface{}
for _, undef := range f.undefined {
if owner != undef.owner {
@@ -323,6 +328,7 @@ func (f *basefmt) Summary() {
owner = undef.owner
}
}
+ passed = total - undefined
var steps, parts, scenarios []string
nsteps := len(f.passed) + len(f.failed) + len(f.skipped) + len(f.undefined) + len(f.pending)
@@ -343,6 +349,9 @@ func (f *basefmt) Summary() {
passed -= undefined
parts = append(parts, yellow(fmt.Sprintf("%d undefined", undefined)))
steps = append(steps, yellow(fmt.Sprintf("%d undefined", len(f.undefined))))
+ } else if undefined > 0 {
+ // there may be some scenarios without steps
+ parts = append(parts, yellow(fmt.Sprintf("%d undefined", undefined)))
}
if len(f.skipped) > 0 {
steps = append(steps, cyan(fmt.Sprintf("%d skipped", len(f.skipped))))
diff --git a/fmt_pretty.go b/fmt_pretty.go
index c4a888e..b13956d 100644
--- a/fmt_pretty.go
+++ b/fmt_pretty.go
@@ -58,7 +58,7 @@ func (f *pretty) Feature(ft *gherkin.Feature, p string, c []byte) {
fmt.Fprintln(f.out, "")
}
f.features = append(f.features, &feature{Path: p, Feature: ft})
- fmt.Fprintln(f.out, whiteb(ft.Keyword+": ")+ft.Name)
+ fmt.Fprintln(f.out, whiteb(ft.Keyword+":")+" "+ft.Name)
if strings.TrimSpace(ft.Description) != "" {
for _, line := range strings.Split(ft.Description, "\n") {
fmt.Fprintln(f.out, s(f.indent)+strings.TrimSpace(line))
@@ -115,7 +115,7 @@ func (f *pretty) printUndefinedScenario(sc *gherkin.Scenario) {
}
f.commentPos = f.longestStep(sc.Steps, f.length(sc))
- text := s(f.indent) + whiteb(f.scenario.Keyword+": ") + sc.Name
+ 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)
}
@@ -209,7 +209,7 @@ func (f *pretty) printOutlineExample(outline *gherkin.ScenarioOutline) {
// an example table header
if firstExample {
fmt.Fprintln(f.out, "")
- fmt.Fprintln(f.out, s(f.indent*2)+whiteb(example.Keyword+": ")+example.Name)
+ fmt.Fprintln(f.out, s(f.indent*2)+whiteb(example.Keyword+":")+" "+example.Name)
for i, cell := range example.TableHeader.Cells {
val := cyan(cell.Value)
@@ -306,7 +306,7 @@ func (f *pretty) printStepKind(res *stepResult) {
f.commentPos = bgLen
}
}
- text := s(f.indent) + whiteb(f.scenario.Keyword+": ") + f.scenario.Name
+ text := s(f.indent) + whiteb(f.scenario.Keyword+":") + " " + f.scenario.Name
text += s(f.commentPos-f.length(f.scenario)+1) + f.line(f.scenario.Location)
fmt.Fprintln(f.out, "\n"+text)
f.scenarioKeyword = true
diff --git a/formatter-tests/pretty/empty b/formatter-tests/pretty/empty
index 97faafc..3850b84 100644
--- a/formatter-tests/pretty/empty
+++ b/formatter-tests/pretty/empty
@@ -1 +1,5 @@
-Feature: empty feature
+Feature: empty feature
+
+No scenarios
+No steps
+0s
diff --git a/formatter-tests/pretty/empty_with_description b/formatter-tests/pretty/empty_with_description
new file mode 100644
index 0000000..6ae0404
--- /dev/null
+++ b/formatter-tests/pretty/empty_with_description
@@ -0,0 +1,8 @@
+Feature: empty feature
+ describes
+ an empty
+ feature
+
+No scenarios
+No steps
+0s
diff --git a/formatter-tests/pretty/empty_with_single_scenario_without_steps b/formatter-tests/pretty/empty_with_single_scenario_without_steps
new file mode 100644
index 0000000..bcff7b1
--- /dev/null
+++ b/formatter-tests/pretty/empty_with_single_scenario_without_steps
@@ -0,0 +1,7 @@
+Feature: empty feature
+
+ Scenario: without steps # formatter-tests/features/empty_with_single_scenario_without_steps.feature:3
+
+1 scenarios (1 undefined)
+No steps
+0s
diff --git a/formatter-tests/pretty/empty_with_single_scenario_without_steps_and_description b/formatter-tests/pretty/empty_with_single_scenario_without_steps_and_description
new file mode 100644
index 0000000..9ac0800
--- /dev/null
+++ b/formatter-tests/pretty/empty_with_single_scenario_without_steps_and_description
@@ -0,0 +1,10 @@
+Feature: empty feature
+ describes
+ an empty
+ feature
+
+ Scenario: without steps # formatter-tests/features/empty_with_single_scenario_without_steps_and_description.feature:6
+
+1 scenarios (1 undefined)
+No steps
+0s
diff --git a/formatter-tests/pretty/single_scenario_with_passing_step b/formatter-tests/pretty/single_scenario_with_passing_step
new file mode 100644
index 0000000..e0dcf32
--- /dev/null
+++ b/formatter-tests/pretty/single_scenario_with_passing_step
@@ -0,0 +1,11 @@
+Feature: single passing scenario
+ describes
+ a single scenario
+ feature
+
+ Scenario: one step passing # formatter-tests/features/single_scenario_with_passing_step.feature:6
+ Given a passing step # formatters_print_test.go:35 -> github.com/DATA-DOG/godog.TestPrintingFormatters.func4
+
+1 scenarios (1 passed)
+1 steps (1 passed)
+0s
diff --git a/formatters_print_test.go b/formatters_print_test.go
index 5d7c8c5..8b4bd51 100644
--- a/formatters_print_test.go
+++ b/formatters_print_test.go
@@ -1 +1,66 @@
package godog
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+)
+
+func TestPrintingFormatters(t *testing.T) {
+ features, err := parseFeatures("", []string{"formatter-tests"})
+ if err != nil {
+ t.Fatalf("failed to parse formatter features: %v", err)
+ }
+
+ var buf bytes.Buffer
+ out := &tagColorWriter{w: &buf}
+
+ suite := &Suite{
+ features: features,
+ }
+
+ suite.Step(`^(?:a )?failing step`, func() error {
+ return fmt.Errorf("step failed")
+ })
+ suite.Step(`^this step should fail`, func() error {
+ return fmt.Errorf("step failed")
+ })
+ suite.Step(`^(?:a )?pending step$`, func() error {
+ return ErrPending
+ })
+ suite.Step(`^(?:a )?passing step$`, func() error {
+ return nil
+ })
+
+ for _, feat := range features {
+ for name := range AvailableFormatters() {
+ expectOutputPath := strings.Replace(feat.Path, "features", name, 1)
+ expectOutputPath = strings.TrimRight(expectOutputPath, ".feature")
+ if _, err := os.Stat(expectOutputPath); err != nil {
+ continue
+ }
+
+ buf.Reset() // flush the output
+ suite.fmt = FindFmt(name)(name, out) // prepare formatter
+ suite.features = []*feature{feat} // set the feature
+
+ expectedOutput, err := ioutil.ReadFile(expectOutputPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ suite.run()
+ suite.fmt.Summary()
+
+ expected := string(expectedOutput)
+ actual := buf.String()
+
+ if actual != expected {
+ t.Fatalf("%s does not match to:\n%s", expectOutputPath, actual)
+ }
+ }
+ }
+}