Merge pull request #392 from vearutop/multi
Use multiple formatters in the same test run
Этот коммит содержится в:
коммит
7cadaeffdb
14 изменённых файлов: 439 добавлений и 33 удалений
133
internal/formatters/fmt_multi.go
Обычный файл
133
internal/formatters/fmt_multi.go
Обычный файл
|
@ -0,0 +1,133 @@
|
||||||
|
package formatters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/cucumber/godog/formatters"
|
||||||
|
"github.com/cucumber/godog/internal/storage"
|
||||||
|
"github.com/cucumber/messages-go/v10"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MultiFormatter passes test progress to multiple formatters.
|
||||||
|
type MultiFormatter struct {
|
||||||
|
formatters []formatter
|
||||||
|
repeater repeater
|
||||||
|
}
|
||||||
|
|
||||||
|
type formatter struct {
|
||||||
|
fmt formatters.FormatterFunc
|
||||||
|
out io.Writer
|
||||||
|
close bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type repeater []formatters.Formatter
|
||||||
|
|
||||||
|
type storageFormatter interface {
|
||||||
|
SetStorage(s *storage.Storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStorage passes storage to all added formatters.
|
||||||
|
func (r repeater) SetStorage(s *storage.Storage) {
|
||||||
|
for _, f := range r {
|
||||||
|
if ss, ok := f.(storageFormatter); ok {
|
||||||
|
ss.SetStorage(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestRunStarted triggers TestRunStarted for all added formatters.
|
||||||
|
func (r repeater) TestRunStarted() {
|
||||||
|
for _, f := range r {
|
||||||
|
f.TestRunStarted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feature triggers Feature for all added formatters.
|
||||||
|
func (r repeater) Feature(document *messages.GherkinDocument, s string, bytes []byte) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Feature(document, s, bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickle triggers Pickle for all added formatters.
|
||||||
|
func (r repeater) Pickle(pickle *messages.Pickle) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Pickle(pickle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defined triggers Defined for all added formatters.
|
||||||
|
func (r repeater) Defined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Defined(pickle, step, definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed triggers Failed for all added formatters.
|
||||||
|
func (r repeater) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition, err error) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Failed(pickle, step, definition, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passed triggers Passed for all added formatters.
|
||||||
|
func (r repeater) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Passed(pickle, step, definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skipped triggers Skipped for all added formatters.
|
||||||
|
func (r repeater) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Skipped(pickle, step, definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undefined triggers Undefined for all added formatters.
|
||||||
|
func (r repeater) Undefined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Undefined(pickle, step, definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pending triggers Pending for all added formatters.
|
||||||
|
func (r repeater) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Pending(pickle, step, definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary triggers Summary for all added formatters.
|
||||||
|
func (r repeater) Summary() {
|
||||||
|
for _, f := range r {
|
||||||
|
f.Summary()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds formatter with output writer.
|
||||||
|
func (m *MultiFormatter) Add(name string, out io.Writer) {
|
||||||
|
f := formatters.FindFmt(name)
|
||||||
|
if f == nil {
|
||||||
|
panic("formatter not found: " + name)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.formatters = append(m.formatters, formatter{
|
||||||
|
fmt: f,
|
||||||
|
out: out,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatterFunc implements the FormatterFunc for the multi formatter.
|
||||||
|
func (m *MultiFormatter) FormatterFunc(suite string, out io.Writer) formatters.Formatter {
|
||||||
|
for _, f := range m.formatters {
|
||||||
|
out := out
|
||||||
|
if f.out != nil {
|
||||||
|
out = f.out
|
||||||
|
}
|
||||||
|
|
||||||
|
m.repeater = append(m.repeater, f.fmt(suite, out))
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.repeater
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ func Test_FmtOutput(t *testing.T) {
|
||||||
featureFiles, err := listFmtOutputTestsFeatureFiles()
|
featureFiles, err := listFmtOutputTestsFeatureFiles()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
formatters := []string{"cucumber", "events", "junit", "pretty", "progress"}
|
formatters := []string{"cucumber", "events", "junit", "pretty", "progress", "junit,pretty"}
|
||||||
|
|
||||||
for _, fmtName := range formatters {
|
for _, fmtName := range formatters {
|
||||||
for _, featureFile := range featureFiles {
|
for _, featureFile := range featureFiles {
|
||||||
|
|
5
internal/formatters/formatter-tests/junit,pretty/empty
Обычный файл
5
internal/formatters/formatter-tests/junit,pretty/empty
Обычный файл
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="0" skipped="0" failures="0" errors="0" time="0"></testsuites>
|
||||||
|
No scenarios
|
||||||
|
No steps
|
||||||
|
0s
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="0" skipped="0" failures="0" errors="0" time="0"></testsuites>
|
||||||
|
No scenarios
|
||||||
|
No steps
|
||||||
|
0s
|
|
@ -0,0 +1,12 @@
|
||||||
|
<bold-white>Feature:</bold-white> empty feature
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> without steps <bold-black># formatter-tests/features/empty_with_single_scenario_without_steps.feature:3</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="empty feature" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="without steps" status="" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
1 scenarios (<yellow>1 undefined</yellow>)
|
||||||
|
No steps
|
||||||
|
0s
|
|
@ -0,0 +1,15 @@
|
||||||
|
<bold-white>Feature:</bold-white> empty feature
|
||||||
|
describes
|
||||||
|
an empty
|
||||||
|
feature
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> without steps <bold-black># formatter-tests/features/empty_with_single_scenario_without_steps_and_description.feature:6</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="empty feature" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="without steps" status="" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
1 scenarios (<yellow>1 undefined</yellow>)
|
||||||
|
No steps
|
||||||
|
0s
|
|
@ -0,0 +1,54 @@
|
||||||
|
<bold-white>Feature:</bold-white> outline
|
||||||
|
|
||||||
|
<bold-white>Scenario Outline:</bold-white> outline <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
|
||||||
|
<cyan>Given</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<cyan>Then</cyan> <cyan>odd </cyan><bold-cyan><odd></bold-cyan><cyan> and even </cyan><bold-cyan><even></bold-cyan><cyan> number</cyan> <bold-black># fmt_output_test.go:103 -> github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Examples:</bold-white> tagged
|
||||||
|
| <cyan>odd</cyan> | <cyan>even</cyan> |
|
||||||
|
| <green>1</green> | <green>2</green> |
|
||||||
|
| <red>2</red> | <red>0</red> |
|
||||||
|
<bold-red>2 is not odd</bold-red>
|
||||||
|
| <red>3</red> | <red>11</red> |
|
||||||
|
<bold-red>11 is not even</bold-red>
|
||||||
|
|
||||||
|
<bold-white>Examples:</bold-white>
|
||||||
|
| <cyan>odd</cyan> | <cyan>even</cyan> |
|
||||||
|
| <green>1</green> | <green>14</green> |
|
||||||
|
| <red>3</red> | <red>9</red> |
|
||||||
|
<bold-red>9 is not even</bold-red>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="5" skipped="0" failures="3" errors="0" time="0">
|
||||||
|
<testsuite name="outline" tests="5" skipped="0" failures="3" errors="0" time="0">
|
||||||
|
<testcase name="outline #1" status="passed" time="0"></testcase>
|
||||||
|
<testcase name="outline #2" status="failed" time="0">
|
||||||
|
<failure message="Step odd 2 and even 0 number: 2 is not odd"></failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="outline #3" status="failed" time="0">
|
||||||
|
<failure message="Step odd 3 and even 11 number: 11 is not even"></failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="outline #4" status="passed" time="0"></testcase>
|
||||||
|
<testcase name="outline #5" status="failed" time="0">
|
||||||
|
<failure message="Step odd 3 and even 9 number: 9 is not even"></failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
--- <red>Failed steps:</red>
|
||||||
|
|
||||||
|
<red>Scenario Outline: outline</red> <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
|
||||||
|
<red>Then odd 2 and even 0 number</red> <bold-black># formatter-tests/features/scenario_outline.feature:8</bold-black>
|
||||||
|
<red>Error: </red><bold-red>2 is not odd</bold-red>
|
||||||
|
|
||||||
|
<red>Scenario Outline: outline</red> <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
|
||||||
|
<red>Then odd 3 and even 11 number</red> <bold-black># formatter-tests/features/scenario_outline.feature:8</bold-black>
|
||||||
|
<red>Error: </red><bold-red>11 is not even</bold-red>
|
||||||
|
|
||||||
|
<red>Scenario Outline: outline</red> <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
|
||||||
|
<red>Then odd 3 and even 9 number</red> <bold-black># formatter-tests/features/scenario_outline.feature:8</bold-black>
|
||||||
|
<red>Error: </red><bold-red>9 is not even</bold-red>
|
||||||
|
|
||||||
|
|
||||||
|
5 scenarios (<green>2 passed</green>, <red>3 failed</red>)
|
||||||
|
15 steps (<green>12 passed</green>, <red>3 failed</red>)
|
||||||
|
0s
|
|
@ -0,0 +1,18 @@
|
||||||
|
<bold-white>Feature:</bold-white> single scenario with background
|
||||||
|
|
||||||
|
<bold-white>Background:</bold-white> named
|
||||||
|
<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>Scenario:</bold-white> scenario <bold-black># formatter-tests/features/scenario_with_background.feature:7</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>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="single scenario with background" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="scenario" status="passed" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
1 scenarios (<green>1 passed</green>)
|
||||||
|
4 steps (<green>4 passed</green>)
|
||||||
|
0s
|
|
@ -0,0 +1,15 @@
|
||||||
|
<bold-white>Feature:</bold-white> empty feature
|
||||||
|
|
||||||
|
<bold-white>Background:</bold-white>
|
||||||
|
<cyan>Given</cyan> <cyan>passing step</cyan>
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> without steps <bold-black># formatter-tests/features/scenario_without_steps_with_background.feature:6</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="empty feature" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="without steps" status="" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
1 scenarios (<yellow>1 undefined</yellow>)
|
||||||
|
No steps
|
||||||
|
0s
|
|
@ -0,0 +1,16 @@
|
||||||
|
<bold-white>Feature:</bold-white> single passing scenario
|
||||||
|
describes
|
||||||
|
a single scenario
|
||||||
|
feature
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> one step passing <bold-black># formatter-tests/features/single_scenario_with_passing_step.feature:6</bold-black>
|
||||||
|
<green>Given</green> <green>a passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="single passing scenario" tests="1" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="one step passing" status="passed" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
1 scenarios (<green>1 passed</green>)
|
||||||
|
1 steps (<green>1 passed</green>)
|
||||||
|
0s
|
|
@ -0,0 +1,54 @@
|
||||||
|
<bold-white>Feature:</bold-white> some scenarios
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> failing <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:3</bold-black>
|
||||||
|
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<red>When</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
|
||||||
|
<bold-red>step failed</bold-red>
|
||||||
|
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> pending <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:8</bold-black>
|
||||||
|
<yellow>When</yellow> <yellow>pending step</yellow> <bold-black># fmt_output_test.go:115 -> github.com/cucumber/godog/internal/formatters_test.pendingStepDef</bold-black>
|
||||||
|
<yellow>TODO: write pending definition</yellow>
|
||||||
|
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> undefined <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:12</bold-black>
|
||||||
|
<yellow>When</yellow> <yellow>undefined</yellow>
|
||||||
|
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="3" skipped="0" failures="1" errors="2" time="0">
|
||||||
|
<testsuite name="some scenarios" tests="3" skipped="0" failures="1" errors="2" time="0">
|
||||||
|
<testcase name="failing" status="failed" time="0">
|
||||||
|
<failure message="Step failing step: step failed"></failure>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="pending" status="pending" time="0">
|
||||||
|
<error message="Step pending step: TODO: write pending definition" type="pending"></error>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="undefined" status="undefined" time="0">
|
||||||
|
<error message="Step undefined" type="undefined"></error>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
--- <red>Failed steps:</red>
|
||||||
|
|
||||||
|
<red>Scenario: failing</red> <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:3</bold-black>
|
||||||
|
<red>When failing step</red> <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:5</bold-black>
|
||||||
|
<red>Error: </red><bold-red>step failed</bold-red>
|
||||||
|
|
||||||
|
|
||||||
|
3 scenarios (<red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 undefined</yellow>)
|
||||||
|
7 steps (<green>1 passed</green>, <red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 undefined</yellow>, <cyan>3 skipped</cyan>)
|
||||||
|
0s
|
||||||
|
|
||||||
|
<yellow>You can implement step definitions for undefined steps with these snippets:</yellow>
|
||||||
|
<yellow>
|
||||||
|
func undefined() error {
|
||||||
|
return godog.ErrPending
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||||
|
ctx.Step(`^undefined$`, undefined)
|
||||||
|
}
|
||||||
|
</yellow>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<bold-white>Feature:</bold-white> two scenarios with background fail
|
||||||
|
|
||||||
|
<bold-white>Background:</bold-white>
|
||||||
|
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<red>And</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
|
||||||
|
<bold-red>step failed</bold-red>
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> one <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:7</bold-black>
|
||||||
|
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> two <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:11</bold-black>
|
||||||
|
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="2" skipped="0" failures="2" errors="0" time="0">
|
||||||
|
<testsuite name="two scenarios with background fail" tests="2" skipped="0" failures="2" errors="0" time="0">
|
||||||
|
<testcase name="one" status="failed" time="0">
|
||||||
|
<failure message="Step failing step: step failed"></failure>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="two" status="failed" time="0">
|
||||||
|
<failure message="Step failing step: step failed"></failure>
|
||||||
|
<error message="Step passing step" type="skipped"></error>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
--- <red>Failed steps:</red>
|
||||||
|
|
||||||
|
<red>Scenario: one</red> <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:7</bold-black>
|
||||||
|
<red>And failing step</red> <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:5</bold-black>
|
||||||
|
<red>Error: </red><bold-red>step failed</bold-red>
|
||||||
|
|
||||||
|
<red>Scenario: two</red> <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:11</bold-black>
|
||||||
|
<red>And failing step</red> <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:5</bold-black>
|
||||||
|
<red>Error: </red><bold-red>step failed</bold-red>
|
||||||
|
|
||||||
|
|
||||||
|
2 scenarios (<red>2 failed</red>)
|
||||||
|
7 steps (<green>2 passed</green>, <red>2 failed</red>, <cyan>3 skipped</cyan>)
|
||||||
|
0s
|
|
@ -0,0 +1,29 @@
|
||||||
|
<bold-white>Feature:</bold-white> few empty scenarios
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> one <bold-black># formatter-tests/features/with_few_empty_scenarios.feature:3</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Scenario Outline:</bold-white> two <bold-black># formatter-tests/features/with_few_empty_scenarios.feature:5</bold-black>
|
||||||
|
|
||||||
|
<bold-white>Examples:</bold-white> first group
|
||||||
|
| <cyan>one</cyan> | <cyan>two</cyan> |
|
||||||
|
| <cyan>1</cyan> | <cyan>2</cyan> |
|
||||||
|
| <cyan>4</cyan> | <cyan>7</cyan> |
|
||||||
|
|
||||||
|
<bold-white>Examples:</bold-white> second group
|
||||||
|
| <cyan>one</cyan> | <cyan>two</cyan> |
|
||||||
|
| <cyan>5</cyan> | <cyan>9</cyan> |
|
||||||
|
|
||||||
|
<bold-white>Scenario:</bold-white> three <bold-black># formatter-tests/features/with_few_empty_scenarios.feature:16</bold-black>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="junit,pretty" tests="5" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testsuite name="few empty scenarios" tests="5" skipped="0" failures="0" errors="0" time="0">
|
||||||
|
<testcase name="one" status="" time="0"></testcase>
|
||||||
|
<testcase name="two #1" status="" time="0"></testcase>
|
||||||
|
<testcase name="two #2" status="" time="0"></testcase>
|
||||||
|
<testcase name="two #3" status="" time="0"></testcase>
|
||||||
|
<testcase name="three" status="" time="0"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
5 scenarios (<yellow>5 undefined</yellow>)
|
||||||
|
No steps
|
||||||
|
0s
|
73
run.go
73
run.go
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"github.com/cucumber/godog/colors"
|
"github.com/cucumber/godog/colors"
|
||||||
"github.com/cucumber/godog/formatters"
|
"github.com/cucumber/godog/formatters"
|
||||||
|
ifmt "github.com/cucumber/godog/internal/formatters"
|
||||||
"github.com/cucumber/godog/internal/models"
|
"github.com/cucumber/godog/internal/models"
|
||||||
"github.com/cucumber/godog/internal/parser"
|
"github.com/cucumber/godog/internal/parser"
|
||||||
"github.com/cucumber/godog/internal/storage"
|
"github.com/cucumber/godog/internal/storage"
|
||||||
|
@ -141,28 +142,49 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
|
||||||
output = opt.Output
|
output = opt.Output
|
||||||
}
|
}
|
||||||
|
|
||||||
if formatterParts := strings.SplitN(opt.Format, ":", 2); len(formatterParts) > 1 {
|
multiFmt := ifmt.MultiFormatter{}
|
||||||
f, err := os.Create(formatterParts[1])
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf(
|
|
||||||
`couldn't create file with name: "%s", error: %s`,
|
|
||||||
formatterParts[1], err.Error(),
|
|
||||||
)
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
|
|
||||||
|
for _, formatter := range strings.Split(opt.Format, ",") {
|
||||||
|
out := output
|
||||||
|
formatterParts := strings.SplitN(formatter, ":", 2)
|
||||||
|
|
||||||
|
if len(formatterParts) > 1 {
|
||||||
|
f, err := os.Create(formatterParts[1])
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
`couldn't create file with name: "%s", error: %s`,
|
||||||
|
formatterParts[1], err.Error(),
|
||||||
|
)
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|
||||||
|
return exitOptionError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
out = f
|
||||||
|
}
|
||||||
|
|
||||||
|
if opt.NoColors {
|
||||||
|
out = colors.Uncolored(out)
|
||||||
|
} else {
|
||||||
|
out = colors.Colored(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil == formatters.FindFmt(formatterParts[0]) {
|
||||||
|
var names []string
|
||||||
|
for name := range formatters.AvailableFormatters() {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Errorf(
|
||||||
|
`unregistered formatter name: "%s", use one of: %s`,
|
||||||
|
opt.Format,
|
||||||
|
strings.Join(names, ", "),
|
||||||
|
))
|
||||||
return exitOptionError
|
return exitOptionError
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.Close()
|
multiFmt.Add(formatterParts[0], out)
|
||||||
|
|
||||||
output = f
|
|
||||||
opt.Format = formatterParts[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if opt.NoColors {
|
|
||||||
output = colors.Uncolored(output)
|
|
||||||
} else {
|
|
||||||
output = colors.Colored(output)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.ShowStepDefinitions {
|
if opt.ShowStepDefinitions {
|
||||||
|
@ -184,20 +206,7 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
|
||||||
opt.Concurrency = 1
|
opt.Concurrency = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
formatter := formatters.FindFmt(opt.Format)
|
runner.fmt = multiFmt.FormatterFunc(suiteName, output)
|
||||||
if nil == formatter {
|
|
||||||
var names []string
|
|
||||||
for name := range formatters.AvailableFormatters() {
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(os.Stderr, fmt.Errorf(
|
|
||||||
`unregistered formatter name: "%s", use one of: %s`,
|
|
||||||
opt.Format,
|
|
||||||
strings.Join(names, ", "),
|
|
||||||
))
|
|
||||||
return exitOptionError
|
|
||||||
}
|
|
||||||
runner.fmt = formatter(suiteName, output)
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if runner.features, err = parser.ParseFeatures(opt.Tags, opt.Paths); err != nil {
|
if runner.features, err = parser.ParseFeatures(opt.Tags, opt.Paths); err != nil {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче