Added features/formatter/pretty.feature
Этот коммит содержится в:
родитель
58d12bc7e6
коммит
de8b0f071b
17 изменённых файлов: 1205 добавлений и 5042 удалений
|
@ -14,7 +14,7 @@ Feature: event stream formatter
|
|||
"""
|
||||
|
||||
Scenario: should process simple scenario
|
||||
Given a feature path "features/load.feature:24"
|
||||
Given a feature path "features/load.feature:25"
|
||||
When I run feature suite with formatter "events"
|
||||
Then the following events should be fired:
|
||||
"""
|
||||
|
@ -35,7 +35,7 @@ Feature: event stream formatter
|
|||
"""
|
||||
|
||||
Scenario: should process outline scenario
|
||||
Given a feature path "features/load.feature:32"
|
||||
Given a feature path "features/load.feature:33"
|
||||
When I run feature suite with formatter "events"
|
||||
Then the following events should be fired:
|
||||
"""
|
||||
|
|
288
features/formatter/pretty.feature
Обычный файл
288
features/formatter/pretty.feature
Обычный файл
|
@ -0,0 +1,288 @@
|
|||
Feature: pretty formatter
|
||||
In order to support tools that import pretty output
|
||||
I need to be able to support pretty formatted output
|
||||
|
||||
Scenario: Support of Feature Plus Scenario Node
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
Scenario: simple scenario
|
||||
simple scenario description
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:3
|
||||
|
||||
1 scenarios (1 undefined)
|
||||
No steps
|
||||
0s
|
||||
"""
|
||||
|
||||
Scenario: Support of Feature Plus Scenario Node With Tags
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
@TAG1
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
@TAG2 @TAG3
|
||||
Scenario: simple scenario
|
||||
simple scenario description
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:5
|
||||
|
||||
1 scenarios (1 undefined)
|
||||
No steps
|
||||
0s
|
||||
"""
|
||||
Scenario: Support of Feature Plus Scenario Outline
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario Outline: simple scenario
|
||||
simple scenario description
|
||||
|
||||
Examples: simple examples
|
||||
| status |
|
||||
| pass |
|
||||
| fail |
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario Outline: simple scenario # features/simple.feature:4
|
||||
|
||||
Examples: simple examples
|
||||
| status |
|
||||
| pass |
|
||||
| fail |
|
||||
|
||||
2 scenarios (2 undefined)
|
||||
No steps
|
||||
0s
|
||||
"""
|
||||
|
||||
Scenario: Support of Feature Plus Scenario Outline With Tags
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
@TAG1
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
@TAG2
|
||||
Scenario Outline: simple scenario
|
||||
simple scenario description
|
||||
|
||||
@TAG3
|
||||
Examples: simple examples
|
||||
| status |
|
||||
| pass |
|
||||
| fail |
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario Outline: simple scenario # features/simple.feature:6
|
||||
|
||||
Examples: simple examples
|
||||
| status |
|
||||
| pass |
|
||||
| fail |
|
||||
|
||||
2 scenarios (2 undefined)
|
||||
No steps
|
||||
0s
|
||||
"""
|
||||
Scenario: Support of Feature Plus Scenario With Steps
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario
|
||||
simple scenario description
|
||||
|
||||
Given passing step
|
||||
Then a failing step
|
||||
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:4
|
||||
Given passing step # suite_context.go:72 -> github.com/cucumber/godog.SuiteContext.func2
|
||||
Then a failing step # suite_context.go:318 -> *suiteContext
|
||||
intentional failure
|
||||
|
||||
--- Failed steps:
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:4
|
||||
Then a failing step # features/simple.feature:8
|
||||
Error: intentional failure
|
||||
|
||||
|
||||
1 scenarios (1 failed)
|
||||
2 steps (1 passed, 1 failed)
|
||||
0s
|
||||
"""
|
||||
Scenario: Support of Feature Plus Scenario Outline With Steps
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature 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
|
||||
simple feature description
|
||||
|
||||
Scenario Outline: simple scenario # features/simple.feature:4
|
||||
Given <status> step # suite_context.go:72 -> github.com/cucumber/godog.SuiteContext.func2
|
||||
|
||||
Examples: simple examples
|
||||
| status |
|
||||
| passing |
|
||||
| failing |
|
||||
intentional failure
|
||||
|
||||
--- Failed steps:
|
||||
|
||||
Scenario Outline: simple scenario # features/simple.feature:4
|
||||
Given failing step # features/simple.feature:7
|
||||
Error: intentional failure
|
||||
|
||||
|
||||
2 scenarios (1 passed, 1 failed)
|
||||
2 steps (1 passed, 1 failed)
|
||||
0s
|
||||
"""
|
||||
|
||||
# Currently godog only supports comments on Feature and not
|
||||
# scenario and steps.
|
||||
Scenario: Support of Comments
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
#Feature comment
|
||||
Feature: simple feature
|
||||
simple description
|
||||
|
||||
Scenario: simple scenario
|
||||
simple feature description
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:5
|
||||
|
||||
1 scenarios (1 undefined)
|
||||
No steps
|
||||
0s
|
||||
"""
|
||||
Scenario: Support of Docstrings
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple description
|
||||
|
||||
Scenario: simple scenario
|
||||
simple feature description
|
||||
|
||||
Given passing step
|
||||
\"\"\" content type
|
||||
step doc string
|
||||
\"\"\"
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:4
|
||||
Given passing step # suite_context.go:72 -> github.com/cucumber/godog.SuiteContext.func2
|
||||
\"\"\" content type
|
||||
step doc string
|
||||
\"\"\"
|
||||
|
||||
1 scenarios (1 passed)
|
||||
1 steps (1 passed)
|
||||
0s
|
||||
"""
|
||||
Scenario: Support of Undefined, Pending and Skipped status
|
||||
Given a feature "features/simple.feature" file:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario
|
||||
simple scenario description
|
||||
|
||||
Given passing step
|
||||
And pending step
|
||||
And undefined
|
||||
And passing step
|
||||
|
||||
"""
|
||||
When I run feature suite with formatter "pretty"
|
||||
Then the rendered output will be as follows:
|
||||
"""
|
||||
Feature: simple feature
|
||||
simple feature description
|
||||
|
||||
Scenario: simple scenario # features/simple.feature:4
|
||||
Given passing step # suite_context.go:72 -> github.com/cucumber/godog.SuiteContext.func2
|
||||
And pending step # suite_context.go:69 -> github.com/cucumber/godog.SuiteContext.func1
|
||||
TODO: write pending definition
|
||||
And undefined
|
||||
And passing step # suite_context.go:72 -> github.com/cucumber/godog.SuiteContext.func2
|
||||
|
||||
1 scenarios (1 pending, 1 undefined)
|
||||
4 steps (1 passed, 1 pending, 1 undefined, 1 skipped)
|
||||
0s
|
||||
|
||||
You can implement step definitions for undefined steps with these snippets:
|
||||
|
||||
func undefined() error {
|
||||
return godog.ErrPending
|
||||
}
|
||||
|
||||
func FeatureContext(s *godog.Suite) {
|
||||
s.Step(`^undefined$`, undefined)
|
||||
}
|
||||
"""
|
|
@ -8,12 +8,13 @@ Savybė: užkrauti savybes
|
|||
Scenarijus: savybių užkrovimas iš aplanko
|
||||
Duota savybių aplankas "features"
|
||||
Kai aš išskaitau savybes
|
||||
Tada aš turėčiau turėti 11 savybių failus:
|
||||
Tada aš turėčiau turėti 12 savybių failus:
|
||||
"""
|
||||
features/background.feature
|
||||
features/events.feature
|
||||
features/formatter/cucumber.feature
|
||||
features/formatter/events.feature
|
||||
features/formatter/pretty.feature
|
||||
features/lang.feature
|
||||
features/load.feature
|
||||
features/multistep.feature
|
||||
|
|
|
@ -6,12 +6,13 @@ Feature: load features
|
|||
Scenario: load features within path
|
||||
Given a feature path "features"
|
||||
When I parse features
|
||||
Then I should have 11 feature files:
|
||||
Then I should have 12 feature files:
|
||||
"""
|
||||
features/background.feature
|
||||
features/events.feature
|
||||
features/formatter/cucumber.feature
|
||||
features/formatter/events.feature
|
||||
features/formatter/pretty.feature
|
||||
features/lang.feature
|
||||
features/load.feature
|
||||
features/multistep.feature
|
||||
|
|
Различия файлов не показаны, т.к. их слишком много
Показать различия
Различия файлов не показаны, т.к. их слишком много
Показать различия
|
@ -1,7 +0,0 @@
|
|||
// +build go1.12
|
||||
|
||||
package fixtures
|
||||
|
||||
const OutputFilenameProgress = "fixtures/progress_output.txt"
|
||||
const OutputFilenameJUnit = "fixtures/junit_output.xml"
|
||||
const OutputFilenameCucumber = "fixtures/cucumber_output.json"
|
|
@ -1,7 +0,0 @@
|
|||
// +build !go1.12
|
||||
|
||||
package fixtures
|
||||
|
||||
const OutputFilenameProgress = "fixtures/progress_output.txt"
|
||||
const OutputFilenameJUnit = "fixtures/junit_output.xml"
|
||||
const OutputFilenameCucumber = "fixtures/cucumber_output_go111.json"
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="succeed" tests="60" skipped="0" failures="0" errors="0" time="0s">
|
||||
<testsuites name="succeed" tests="69" skipped="0" failures="0" errors="0" time="0s">
|
||||
<testsuite name="cucumber json formatter" tests="9" skipped="0" failures="0" errors="0" time="0s">
|
||||
<testcase name="Support of Feature Plus Scenario Node" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario Node With Tags" status="passed" time="0s"></testcase>
|
||||
|
@ -24,6 +24,17 @@
|
|||
<testcase name="loaded feature should have a number of scenarios #3" status="passed" time="0s"></testcase>
|
||||
<testcase name="load a number of feature files" status="passed" time="0s"></testcase>
|
||||
</testsuite>
|
||||
<testsuite name="pretty formatter" tests="9" skipped="0" failures="0" errors="0" time="0s">
|
||||
<testcase name="Support of Feature Plus Scenario Node" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario Node With Tags" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario Outline" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario Outline With Tags" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario With Steps" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Feature Plus Scenario Outline With Steps" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Comments" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Docstrings" status="passed" time="0s"></testcase>
|
||||
<testcase name="Support of Undefined, Pending and Skipped status" status="passed" time="0s"></testcase>
|
||||
</testsuite>
|
||||
<testsuite name="run background" tests="3" skipped="0" failures="0" errors="0" time="0s">
|
||||
<testcase name="should run background steps" status="passed" time="0s"></testcase>
|
||||
<testcase name="should skip all consequent steps on failure" status="passed" time="0s"></testcase>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
...................................................................... 70
|
||||
...................................................................... 140
|
||||
...................................................................... 210
|
||||
....................................... 249
|
||||
.................................................................. 276
|
||||
|
||||
|
||||
60 scenarios (60 passed)
|
||||
249 steps (249 passed)
|
||||
69 scenarios (69 passed)
|
||||
276 steps (276 passed)
|
||||
0s
|
|
@ -76,14 +76,6 @@ func FeatureContext(s *godog.Suite) {
|
|||
shouldMatchOutput(expected, actual, t)
|
||||
}
|
||||
|
||||
func trimAllLines(s string) string {
|
||||
var lines []string
|
||||
for _, ln := range strings.Split(strings.TrimSpace(s), "\n") {
|
||||
lines = append(lines, strings.TrimSpace(ln))
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
var basicGherkinFeature = `
|
||||
Feature: basic
|
||||
|
||||
|
@ -114,7 +106,7 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
|
|||
}
|
||||
|
||||
out := buf.String()
|
||||
if idx := strings.Index(out, "godog/fmt_progress_test.go:108"); idx == -1 {
|
||||
if idx := strings.Index(out, "godog/fmt_progress_test.go:100"); idx == -1 {
|
||||
t.Fatalf("expected to find panic stacktrace, actual:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module github.com/cucumber/godog
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.4.0
|
||||
|
|
11
go.sum
11
go.sum
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
131
run_test.go
131
run_test.go
|
@ -6,11 +6,14 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cucumber/godog/colors"
|
||||
"github.com/cucumber/godog/fixtures"
|
||||
"github.com/cucumber/godog/gherkin"
|
||||
)
|
||||
|
||||
|
@ -52,16 +55,12 @@ func TestPrintsNoStepDefinitionsIfNoneFound(t *testing.T) {
|
|||
s.printStepDefinitions(w)
|
||||
|
||||
out := strings.TrimSpace(buf.String())
|
||||
if out != "there were no contexts registered, could not find any step definition.." {
|
||||
t.Fatalf("expected output does not match to: %s", out)
|
||||
}
|
||||
assert.Equal(t, "there were no contexts registered, could not find any step definition..", out)
|
||||
}
|
||||
|
||||
func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
|
||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
r := runner{
|
||||
fmt: progressFunc("progress", ioutil.Discard),
|
||||
|
@ -72,21 +71,15 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if r.run() {
|
||||
t.Fatal("the suite should have passed")
|
||||
}
|
||||
assert.False(t, r.run())
|
||||
|
||||
r.strict = true
|
||||
if !r.run() {
|
||||
t.Fatal("the suite should have failed")
|
||||
}
|
||||
assert.True(t, r.run())
|
||||
}
|
||||
|
||||
func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
|
||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
r := runner{
|
||||
fmt: progressFunc("progress", ioutil.Discard),
|
||||
|
@ -97,21 +90,15 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if r.run() {
|
||||
t.Fatal("the suite should have passed")
|
||||
}
|
||||
assert.False(t, r.run())
|
||||
|
||||
r.strict = true
|
||||
if !r.run() {
|
||||
t.Fatal("the suite should have failed")
|
||||
}
|
||||
assert.True(t, r.run())
|
||||
}
|
||||
|
||||
func TestShouldFailOnError(t *testing.T) {
|
||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
r := runner{
|
||||
fmt: progressFunc("progress", ioutil.Discard),
|
||||
|
@ -122,9 +109,7 @@ func TestShouldFailOnError(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if !r.run() {
|
||||
t.Fatal("the suite should have failed")
|
||||
}
|
||||
assert.True(t, r.run())
|
||||
}
|
||||
|
||||
func TestFailsWithConcurrencyOptionError(t *testing.T) {
|
||||
|
@ -140,20 +125,15 @@ func TestFailsWithConcurrencyOptionError(t *testing.T) {
|
|||
}
|
||||
|
||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||
if status != exitOptionError {
|
||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
||||
}
|
||||
require.Equal(t, exitOptionError, status)
|
||||
|
||||
closer()
|
||||
|
||||
b, err := ioutil.ReadAll(stderr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
out := strings.TrimSpace(string(b))
|
||||
if out != `format "pretty" does not support concurrent execution` {
|
||||
t.Fatalf("unexpected error output: \"%s\"", out)
|
||||
}
|
||||
assert.Equal(t, `format "pretty" does not support concurrent execution`, out)
|
||||
}
|
||||
|
||||
func TestFailsWithUnknownFormatterOptionError(t *testing.T) {
|
||||
|
@ -168,20 +148,15 @@ func TestFailsWithUnknownFormatterOptionError(t *testing.T) {
|
|||
}
|
||||
|
||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||
if status != exitOptionError {
|
||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
||||
}
|
||||
require.Equal(t, exitOptionError, status)
|
||||
|
||||
closer()
|
||||
|
||||
b, err := ioutil.ReadAll(stderr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
out := strings.TrimSpace(string(b))
|
||||
if !strings.Contains(out, `unregistered formatter name: "unknown", use one of`) {
|
||||
t.Fatalf("unexpected error output: %q", out)
|
||||
}
|
||||
assert.Contains(t, out, `unregistered formatter name: "unknown", use one of`)
|
||||
}
|
||||
|
||||
func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.T) {
|
||||
|
@ -196,20 +171,15 @@ func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.
|
|||
}
|
||||
|
||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||
if status != exitOptionError {
|
||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
||||
}
|
||||
require.Equal(t, exitOptionError, status)
|
||||
|
||||
closer()
|
||||
|
||||
b, err := ioutil.ReadAll(stderr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
out := strings.TrimSpace(string(b))
|
||||
if out != `feature path "unavailable" is not available` {
|
||||
t.Fatalf("unexpected error output: \"%s\"", out)
|
||||
}
|
||||
assert.Equal(t, `feature path "unavailable" is not available`, out)
|
||||
}
|
||||
|
||||
func TestByDefaultRunsFeaturesPath(t *testing.T) {
|
||||
|
@ -221,24 +191,18 @@ func TestByDefaultRunsFeaturesPath(t *testing.T) {
|
|||
|
||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||
// should fail in strict mode due to undefined steps
|
||||
if status != exitFailure {
|
||||
t.Fatalf("expected exit status to be 1, but was: %d", status)
|
||||
}
|
||||
assert.Equal(t, exitFailure, status)
|
||||
|
||||
opt.Strict = false
|
||||
status = RunWithOptions("succeeds", func(_ *Suite) {}, opt)
|
||||
// should succeed in non strict mode due to undefined steps
|
||||
if status != exitSuccess {
|
||||
t.Fatalf("expected exit status to be 0, but was: %d", status)
|
||||
}
|
||||
assert.Equal(t, exitSuccess, status)
|
||||
}
|
||||
|
||||
func bufErrorPipe(t *testing.T) (io.ReadCloser, func()) {
|
||||
stderr := os.Stderr
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
os.Stderr = w
|
||||
return r, func() {
|
||||
|
@ -266,14 +230,10 @@ func TestFeatureFilePathParser(t *testing.T) {
|
|||
{"D:\\home\\test.feature:3", "D:\\home\\test.feature", 3},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
for _, c := range cases {
|
||||
p, ln := extractFeaturePathLine(c.input)
|
||||
if p != c.path {
|
||||
t.Fatalf(`result path "%s" != "%s" at %d`, p, c.path, i)
|
||||
}
|
||||
if ln != c.line {
|
||||
t.Fatalf(`result line "%d" != "%d" at %d`, ln, c.line, i)
|
||||
}
|
||||
assert.Equal(t, p, c.path)
|
||||
assert.Equal(t, ln, c.line)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,16 +245,14 @@ type succeedRunTestCase struct {
|
|||
|
||||
func TestSucceedRun(t *testing.T) {
|
||||
testCases := []succeedRunTestCase{
|
||||
{format: "progress", concurrency: 4, filename: fixtures.OutputFilenameProgress},
|
||||
{format: "junit", concurrency: 4, filename: fixtures.OutputFilenameJUnit},
|
||||
{format: "cucumber", concurrency: 2, filename: fixtures.OutputFilenameCucumber},
|
||||
{format: "progress", concurrency: 4, filename: "fixtures/progress_output.txt"},
|
||||
{format: "junit", concurrency: 4, filename: "fixtures/junit_output.xml"},
|
||||
{format: "cucumber", concurrency: 2, filename: "fixtures/cucumber_output.json"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
expectedOutput, err := ioutil.ReadFile(tc.filename)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
for concurrency := range make([]int, tc.concurrency) {
|
||||
t.Run(
|
||||
|
@ -319,17 +277,16 @@ func testSucceedRun(t *testing.T, format string, concurrency int, expectedOutput
|
|||
}
|
||||
|
||||
status := RunWithOptions("succeed", func(s *Suite) { SuiteContext(s) }, opt)
|
||||
if status != exitSuccess {
|
||||
t.Fatalf("expected exit status to be 0, but was: %d", status)
|
||||
}
|
||||
require.Equal(t, exitSuccess, status)
|
||||
|
||||
b, err := ioutil.ReadAll(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
out := strings.TrimSpace(string(b))
|
||||
if out != expectedOutput {
|
||||
t.Fatalf("unexpected output: \"%s\"", out)
|
||||
}
|
||||
actual := strings.TrimSpace(string(b))
|
||||
|
||||
suiteCtxReg := regexp.MustCompile(`suite_context.go:\d+`)
|
||||
expectedOutput = suiteCtxReg.ReplaceAllString(expectedOutput, `suite_context.go:0`)
|
||||
actual = suiteCtxReg.ReplaceAllString(actual, `suite_context.go:0`)
|
||||
|
||||
assert.Equalf(t, expectedOutput, actual, "[%s]", actual)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cucumber/godog/colors"
|
||||
"github.com/cucumber/godog/gherkin"
|
||||
)
|
||||
|
||||
|
@ -74,6 +75,9 @@ func SuiteContext(s *Suite, additionalContextInitializers ...func(suite *Suite))
|
|||
// Introduced to test formatter/cucumber.feature
|
||||
s.Step(`^the rendered json will be as follows:$`, c.theRenderJSONWillBe)
|
||||
|
||||
// Introduced to test formatter/pretty.feature
|
||||
s.Step(`^the rendered output will be as follows:$`, c.theRenderOutputWillBe)
|
||||
|
||||
s.Step(`^(?:a )?failing multistep$`, func() Steps {
|
||||
return Steps{"passing step", "failing step"}
|
||||
})
|
||||
|
@ -133,7 +137,8 @@ func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error {
|
|||
if f == nil {
|
||||
return fmt.Errorf(`formatter "%s" is not available`, name)
|
||||
}
|
||||
s.testedSuite.fmt = f("godog", &s.out)
|
||||
|
||||
s.testedSuite.fmt = f("godog", colors.Uncolored(&s.out))
|
||||
if err := s.parseFeatures(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -457,14 +462,14 @@ func (s *suiteContext) theseEventsHadToBeFiredForNumberOfTimes(tbl *gherkin.Data
|
|||
}
|
||||
|
||||
func (s *suiteContext) theRenderJSONWillBe(docstring *gherkin.DocString) error {
|
||||
loc := regexp.MustCompile(`"suite_context.go:\d+"`)
|
||||
suiteCtxReg := regexp.MustCompile(`suite_context.go:\d+`)
|
||||
var expected []cukeFeatureJSON
|
||||
if err := json.Unmarshal([]byte(loc.ReplaceAllString(docstring.Content, `"suite_context.go:0"`)), &expected); err != nil {
|
||||
if err := json.Unmarshal([]byte(suiteCtxReg.ReplaceAllString(docstring.Content, `suite_context.go:0`)), &expected); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actual []cukeFeatureJSON
|
||||
replaced := loc.ReplaceAllString(s.out.String(), `"suite_context.go:0"`)
|
||||
replaced := suiteCtxReg.ReplaceAllString(s.out.String(), `suite_context.go:0`)
|
||||
if err := json.Unmarshal([]byte(replaced), &actual); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -475,6 +480,21 @@ func (s *suiteContext) theRenderJSONWillBe(docstring *gherkin.DocString) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *suiteContext) theRenderOutputWillBe(docstring *gherkin.DocString) error {
|
||||
suiteCtxReg := regexp.MustCompile(`suite_context.go:\d+`)
|
||||
|
||||
expected := trimAllLines(strings.TrimSpace(docstring.Content))
|
||||
expected = suiteCtxReg.ReplaceAllString(expected, `suite_context.go:0`)
|
||||
actual := trimAllLines(strings.TrimSpace(s.out.String()))
|
||||
actual = suiteCtxReg.ReplaceAllString(actual, `suite_context.go:0`)
|
||||
|
||||
if expected != actual {
|
||||
return fmt.Errorf("expected output\n%s\ndoes not match actual:\n%s\n", expected, actual)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type testFormatter struct {
|
||||
basefmt
|
||||
scenarios []interface{}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package godog
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
format := "progress" // non verbose mode
|
||||
concurrency := 4
|
||||
|
||||
var specific bool
|
||||
for _, arg := range os.Args[1:] {
|
||||
if arg == "-test.v=true" { // go test transforms -v option - verbose mode
|
||||
format = "pretty"
|
||||
concurrency = 1
|
||||
break
|
||||
}
|
||||
if strings.Index(arg, "-test.run") == 0 {
|
||||
specific = true
|
||||
}
|
||||
}
|
||||
var status int
|
||||
if !specific {
|
||||
status = RunWithOptions("godog", func(s *Suite) {
|
||||
GodogContext(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 {
|
||||
status = st
|
||||
}
|
||||
os.Exit(status)
|
||||
}
|
||||
|
||||
// needed in order to use godog cli
|
||||
func GodogContext(s *Suite) {
|
||||
SuiteContext(s)
|
||||
}
|
8
utils.go
8
utils.go
|
@ -26,3 +26,11 @@ func s(n int) string {
|
|||
var timeNowFunc = func() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func trimAllLines(s string) string {
|
||||
var lines []string
|
||||
for _, ln := range strings.Split(strings.TrimSpace(s), "\n") {
|
||||
lines = append(lines, strings.TrimSpace(ln))
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче