Added features/formatter/pretty.feature
Этот коммит содержится в:
родитель
58d12bc7e6
коммит
de8b0f071b
17 изменённых файлов: 1205 добавлений и 5042 удалений
|
@ -14,7 +14,7 @@ Feature: event stream formatter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: should process simple scenario
|
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"
|
When I run feature suite with formatter "events"
|
||||||
Then the following events should be fired:
|
Then the following events should be fired:
|
||||||
"""
|
"""
|
||||||
|
@ -35,7 +35,7 @@ Feature: event stream formatter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: should process outline scenario
|
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"
|
When I run feature suite with formatter "events"
|
||||||
Then the following events should be fired:
|
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
|
Scenarijus: savybių užkrovimas iš aplanko
|
||||||
Duota savybių aplankas "features"
|
Duota savybių aplankas "features"
|
||||||
Kai aš išskaitau savybes
|
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/background.feature
|
||||||
features/events.feature
|
features/events.feature
|
||||||
features/formatter/cucumber.feature
|
features/formatter/cucumber.feature
|
||||||
features/formatter/events.feature
|
features/formatter/events.feature
|
||||||
|
features/formatter/pretty.feature
|
||||||
features/lang.feature
|
features/lang.feature
|
||||||
features/load.feature
|
features/load.feature
|
||||||
features/multistep.feature
|
features/multistep.feature
|
||||||
|
|
|
@ -6,12 +6,13 @@ Feature: load features
|
||||||
Scenario: load features within path
|
Scenario: load features within path
|
||||||
Given a feature path "features"
|
Given a feature path "features"
|
||||||
When I parse features
|
When I parse features
|
||||||
Then I should have 11 feature files:
|
Then I should have 12 feature files:
|
||||||
"""
|
"""
|
||||||
features/background.feature
|
features/background.feature
|
||||||
features/events.feature
|
features/events.feature
|
||||||
features/formatter/cucumber.feature
|
features/formatter/cucumber.feature
|
||||||
features/formatter/events.feature
|
features/formatter/events.feature
|
||||||
|
features/formatter/pretty.feature
|
||||||
features/lang.feature
|
features/lang.feature
|
||||||
features/load.feature
|
features/load.feature
|
||||||
features/multistep.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"?>
|
<?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">
|
<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" 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 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="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>
|
<testcase name="load a number of feature files" status="passed" time="0s"></testcase>
|
||||||
</testsuite>
|
</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">
|
<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 run background steps" status="passed" time="0s"></testcase>
|
||||||
<testcase name="should skip all consequent steps on failure" status="passed" time="0s"></testcase>
|
<testcase name="should skip all consequent steps on failure" status="passed" time="0s"></testcase>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
...................................................................... 70
|
...................................................................... 70
|
||||||
...................................................................... 140
|
...................................................................... 140
|
||||||
...................................................................... 210
|
...................................................................... 210
|
||||||
....................................... 249
|
.................................................................. 276
|
||||||
|
|
||||||
|
|
||||||
60 scenarios (60 passed)
|
69 scenarios (69 passed)
|
||||||
249 steps (249 passed)
|
276 steps (276 passed)
|
||||||
0s
|
0s
|
|
@ -76,14 +76,6 @@ func FeatureContext(s *godog.Suite) {
|
||||||
shouldMatchOutput(expected, actual, t)
|
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 = `
|
var basicGherkinFeature = `
|
||||||
Feature: basic
|
Feature: basic
|
||||||
|
|
||||||
|
@ -114,7 +106,7 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
out := buf.String()
|
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)
|
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
|
module github.com/cucumber/godog
|
||||||
|
|
||||||
go 1.13
|
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"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/cucumber/godog/colors"
|
"github.com/cucumber/godog/colors"
|
||||||
"github.com/cucumber/godog/fixtures"
|
|
||||||
"github.com/cucumber/godog/gherkin"
|
"github.com/cucumber/godog/gherkin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,16 +55,12 @@ func TestPrintsNoStepDefinitionsIfNoneFound(t *testing.T) {
|
||||||
s.printStepDefinitions(w)
|
s.printStepDefinitions(w)
|
||||||
|
|
||||||
out := strings.TrimSpace(buf.String())
|
out := strings.TrimSpace(buf.String())
|
||||||
if out != "there were no contexts registered, could not find any step definition.." {
|
assert.Equal(t, "there were no contexts registered, could not find any step definition..", out)
|
||||||
t.Fatalf("expected output does not match to: %s", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
|
func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
|
||||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := runner{
|
r := runner{
|
||||||
fmt: progressFunc("progress", ioutil.Discard),
|
fmt: progressFunc("progress", ioutil.Discard),
|
||||||
|
@ -72,21 +71,15 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.run() {
|
assert.False(t, r.run())
|
||||||
t.Fatal("the suite should have passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r.strict = true
|
r.strict = true
|
||||||
if !r.run() {
|
assert.True(t, r.run())
|
||||||
t.Fatal("the suite should have failed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
|
func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
|
||||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := runner{
|
r := runner{
|
||||||
fmt: progressFunc("progress", ioutil.Discard),
|
fmt: progressFunc("progress", ioutil.Discard),
|
||||||
|
@ -97,21 +90,15 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.run() {
|
assert.False(t, r.run())
|
||||||
t.Fatal("the suite should have passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r.strict = true
|
r.strict = true
|
||||||
if !r.run() {
|
assert.True(t, r.run())
|
||||||
t.Fatal("the suite should have failed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldFailOnError(t *testing.T) {
|
func TestShouldFailOnError(t *testing.T) {
|
||||||
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := runner{
|
r := runner{
|
||||||
fmt: progressFunc("progress", ioutil.Discard),
|
fmt: progressFunc("progress", ioutil.Discard),
|
||||||
|
@ -122,9 +109,7 @@ func TestShouldFailOnError(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !r.run() {
|
assert.True(t, r.run())
|
||||||
t.Fatal("the suite should have failed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailsWithConcurrencyOptionError(t *testing.T) {
|
func TestFailsWithConcurrencyOptionError(t *testing.T) {
|
||||||
|
@ -140,20 +125,15 @@ func TestFailsWithConcurrencyOptionError(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||||
if status != exitOptionError {
|
require.Equal(t, exitOptionError, status)
|
||||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
|
||||||
}
|
|
||||||
closer()
|
closer()
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(stderr)
|
b, err := ioutil.ReadAll(stderr)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := strings.TrimSpace(string(b))
|
out := strings.TrimSpace(string(b))
|
||||||
if out != `format "pretty" does not support concurrent execution` {
|
assert.Equal(t, `format "pretty" does not support concurrent execution`, out)
|
||||||
t.Fatalf("unexpected error output: \"%s\"", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailsWithUnknownFormatterOptionError(t *testing.T) {
|
func TestFailsWithUnknownFormatterOptionError(t *testing.T) {
|
||||||
|
@ -168,20 +148,15 @@ func TestFailsWithUnknownFormatterOptionError(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||||
if status != exitOptionError {
|
require.Equal(t, exitOptionError, status)
|
||||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
|
||||||
}
|
|
||||||
closer()
|
closer()
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(stderr)
|
b, err := ioutil.ReadAll(stderr)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := strings.TrimSpace(string(b))
|
out := strings.TrimSpace(string(b))
|
||||||
if !strings.Contains(out, `unregistered formatter name: "unknown", use one of`) {
|
assert.Contains(t, out, `unregistered formatter name: "unknown", use one of`)
|
||||||
t.Fatalf("unexpected error output: %q", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.T) {
|
func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.T) {
|
||||||
|
@ -196,20 +171,15 @@ func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.
|
||||||
}
|
}
|
||||||
|
|
||||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||||
if status != exitOptionError {
|
require.Equal(t, exitOptionError, status)
|
||||||
t.Fatalf("expected exit status to be 2, but was: %d", status)
|
|
||||||
}
|
|
||||||
closer()
|
closer()
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(stderr)
|
b, err := ioutil.ReadAll(stderr)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := strings.TrimSpace(string(b))
|
out := strings.TrimSpace(string(b))
|
||||||
if out != `feature path "unavailable" is not available` {
|
assert.Equal(t, `feature path "unavailable" is not available`, out)
|
||||||
t.Fatalf("unexpected error output: \"%s\"", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestByDefaultRunsFeaturesPath(t *testing.T) {
|
func TestByDefaultRunsFeaturesPath(t *testing.T) {
|
||||||
|
@ -221,24 +191,18 @@ func TestByDefaultRunsFeaturesPath(t *testing.T) {
|
||||||
|
|
||||||
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
status := RunWithOptions("fails", func(_ *Suite) {}, opt)
|
||||||
// should fail in strict mode due to undefined steps
|
// should fail in strict mode due to undefined steps
|
||||||
if status != exitFailure {
|
assert.Equal(t, exitFailure, status)
|
||||||
t.Fatalf("expected exit status to be 1, but was: %d", status)
|
|
||||||
}
|
|
||||||
|
|
||||||
opt.Strict = false
|
opt.Strict = false
|
||||||
status = RunWithOptions("succeeds", func(_ *Suite) {}, opt)
|
status = RunWithOptions("succeeds", func(_ *Suite) {}, opt)
|
||||||
// should succeed in non strict mode due to undefined steps
|
// should succeed in non strict mode due to undefined steps
|
||||||
if status != exitSuccess {
|
assert.Equal(t, exitSuccess, status)
|
||||||
t.Fatalf("expected exit status to be 0, but was: %d", status)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func bufErrorPipe(t *testing.T) (io.ReadCloser, func()) {
|
func bufErrorPipe(t *testing.T) (io.ReadCloser, func()) {
|
||||||
stderr := os.Stderr
|
stderr := os.Stderr
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Stderr = w
|
os.Stderr = w
|
||||||
return r, func() {
|
return r, func() {
|
||||||
|
@ -266,14 +230,10 @@ func TestFeatureFilePathParser(t *testing.T) {
|
||||||
{"D:\\home\\test.feature:3", "D:\\home\\test.feature", 3},
|
{"D:\\home\\test.feature:3", "D:\\home\\test.feature", 3},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, c := range cases {
|
for _, c := range cases {
|
||||||
p, ln := extractFeaturePathLine(c.input)
|
p, ln := extractFeaturePathLine(c.input)
|
||||||
if p != c.path {
|
assert.Equal(t, p, c.path)
|
||||||
t.Fatalf(`result path "%s" != "%s" at %d`, p, c.path, i)
|
assert.Equal(t, ln, c.line)
|
||||||
}
|
|
||||||
if ln != c.line {
|
|
||||||
t.Fatalf(`result line "%d" != "%d" at %d`, ln, c.line, i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,16 +245,14 @@ type succeedRunTestCase struct {
|
||||||
|
|
||||||
func TestSucceedRun(t *testing.T) {
|
func TestSucceedRun(t *testing.T) {
|
||||||
testCases := []succeedRunTestCase{
|
testCases := []succeedRunTestCase{
|
||||||
{format: "progress", concurrency: 4, filename: fixtures.OutputFilenameProgress},
|
{format: "progress", concurrency: 4, filename: "fixtures/progress_output.txt"},
|
||||||
{format: "junit", concurrency: 4, filename: fixtures.OutputFilenameJUnit},
|
{format: "junit", concurrency: 4, filename: "fixtures/junit_output.xml"},
|
||||||
{format: "cucumber", concurrency: 2, filename: fixtures.OutputFilenameCucumber},
|
{format: "cucumber", concurrency: 2, filename: "fixtures/cucumber_output.json"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
expectedOutput, err := ioutil.ReadFile(tc.filename)
|
expectedOutput, err := ioutil.ReadFile(tc.filename)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for concurrency := range make([]int, tc.concurrency) {
|
for concurrency := range make([]int, tc.concurrency) {
|
||||||
t.Run(
|
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)
|
status := RunWithOptions("succeed", func(s *Suite) { SuiteContext(s) }, opt)
|
||||||
if status != exitSuccess {
|
require.Equal(t, exitSuccess, status)
|
||||||
t.Fatalf("expected exit status to be 0, but was: %d", status)
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(output)
|
b, err := ioutil.ReadAll(output)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := strings.TrimSpace(string(b))
|
actual := strings.TrimSpace(string(b))
|
||||||
if out != expectedOutput {
|
|
||||||
t.Fatalf("unexpected output: \"%s\"", out)
|
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"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cucumber/godog/colors"
|
||||||
"github.com/cucumber/godog/gherkin"
|
"github.com/cucumber/godog/gherkin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,6 +75,9 @@ func SuiteContext(s *Suite, additionalContextInitializers ...func(suite *Suite))
|
||||||
// Introduced to test formatter/cucumber.feature
|
// Introduced to test formatter/cucumber.feature
|
||||||
s.Step(`^the rendered json will be as follows:$`, c.theRenderJSONWillBe)
|
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 {
|
s.Step(`^(?:a )?failing multistep$`, func() Steps {
|
||||||
return Steps{"passing step", "failing step"}
|
return Steps{"passing step", "failing step"}
|
||||||
})
|
})
|
||||||
|
@ -133,7 +137,8 @@ func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return fmt.Errorf(`formatter "%s" is not available`, name)
|
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 {
|
if err := s.parseFeatures(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -457,14 +462,14 @@ func (s *suiteContext) theseEventsHadToBeFiredForNumberOfTimes(tbl *gherkin.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *suiteContext) theRenderJSONWillBe(docstring *gherkin.DocString) error {
|
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
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var actual []cukeFeatureJSON
|
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 {
|
if err := json.Unmarshal([]byte(replaced), &actual); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -475,6 +480,21 @@ func (s *suiteContext) theRenderJSONWillBe(docstring *gherkin.DocString) error {
|
||||||
return nil
|
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 {
|
type testFormatter struct {
|
||||||
basefmt
|
basefmt
|
||||||
scenarios []interface{}
|
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 {
|
var timeNowFunc = func() time.Time {
|
||||||
return time.Now()
|
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")
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче