initial tests for event stream formatter
Этот коммит содержится в:
родитель
e71d596404
коммит
c50c2dc368
5 изменённых файлов: 163 добавлений и 13 удалений
78
features/formatter/events.feature
Обычный файл
78
features/formatter/events.feature
Обычный файл
|
@ -0,0 +1,78 @@
|
||||||
|
Feature: event stream formatter
|
||||||
|
In order to have universal cucumber formatter
|
||||||
|
As a test suite
|
||||||
|
I need to be able to support event stream formatter
|
||||||
|
|
||||||
|
Scenario: should fire only suite events without any scenario
|
||||||
|
Given a feature path "features/load.feature:4"
|
||||||
|
When I run feature suite with formatter "events"
|
||||||
|
Then the following events should be fired:
|
||||||
|
"""
|
||||||
|
TestRunStarted
|
||||||
|
TestSource
|
||||||
|
TestRunFinished
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: should process simple scenario
|
||||||
|
Given a feature path "features/load.feature:21"
|
||||||
|
When I run feature suite with formatter "events"
|
||||||
|
Then the following events should be fired:
|
||||||
|
"""
|
||||||
|
TestRunStarted
|
||||||
|
TestSource
|
||||||
|
TestCaseStarted
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
TestCaseFinished
|
||||||
|
TestRunFinished
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: should process outline scenario
|
||||||
|
Given a feature path "features/load.feature:29"
|
||||||
|
When I run feature suite with formatter "events"
|
||||||
|
Then the following events should be fired:
|
||||||
|
"""
|
||||||
|
TestRunStarted
|
||||||
|
TestSource
|
||||||
|
TestCaseStarted
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
TestCaseFinished
|
||||||
|
TestCaseStarted
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
TestCaseFinished
|
||||||
|
TestCaseStarted
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
StepDefinitionFound
|
||||||
|
TestStepStarted
|
||||||
|
TestStepFinished
|
||||||
|
TestCaseFinished
|
||||||
|
TestRunFinished
|
||||||
|
"""
|
|
@ -8,10 +8,11 @@ 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 7 savybių failus:
|
Tada aš turėčiau turėti 8 savybių failus:
|
||||||
"""
|
"""
|
||||||
features/background.feature
|
features/background.feature
|
||||||
features/events.feature
|
features/events.feature
|
||||||
|
features/formatter/events.feature
|
||||||
features/lang.feature
|
features/lang.feature
|
||||||
features/load.feature
|
features/load.feature
|
||||||
features/outline.feature
|
features/outline.feature
|
||||||
|
|
|
@ -6,10 +6,11 @@ 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 7 feature files:
|
Then I should have 8 feature files:
|
||||||
"""
|
"""
|
||||||
features/background.feature
|
features/background.feature
|
||||||
features/events.feature
|
features/events.feature
|
||||||
|
features/formatter/events.feature
|
||||||
features/lang.feature
|
features/lang.feature
|
||||||
features/load.feature
|
features/load.feature
|
||||||
features/outline.feature
|
features/outline.feature
|
||||||
|
|
17
fmt_test.go
17
fmt_test.go
|
@ -1,12 +1,27 @@
|
||||||
package godog
|
package godog
|
||||||
|
|
||||||
import "github.com/DATA-DOG/godog/gherkin"
|
import (
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/DATA-DOG/godog/gherkin"
|
||||||
|
)
|
||||||
|
|
||||||
type testFormatter struct {
|
type testFormatter struct {
|
||||||
basefmt
|
basefmt
|
||||||
scenarios []interface{}
|
scenarios []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testFormatterFunc(out io.Writer) Formatter {
|
||||||
|
return &testFormatter{
|
||||||
|
basefmt: basefmt{
|
||||||
|
started: time.Now(),
|
||||||
|
indent: 2,
|
||||||
|
out: out,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (f *testFormatter) Node(node interface{}) {
|
func (f *testFormatter) Node(node interface{}) {
|
||||||
f.basefmt.Node(node)
|
f.basefmt.Node(node)
|
||||||
switch t := node.(type) {
|
switch t := node.(type) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package godog
|
package godog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -18,6 +20,7 @@ func SuiteContext(s *Suite) {
|
||||||
s.Step(`^I parse features$`, c.parseFeatures)
|
s.Step(`^I parse features$`, c.parseFeatures)
|
||||||
s.Step(`^I'm listening to suite events$`, c.iAmListeningToSuiteEvents)
|
s.Step(`^I'm listening to suite events$`, c.iAmListeningToSuiteEvents)
|
||||||
s.Step(`^I run feature suite$`, c.iRunFeatureSuite)
|
s.Step(`^I run feature suite$`, c.iRunFeatureSuite)
|
||||||
|
s.Step(`^I run feature suite with formatter "([^"]*)"$`, c.iRunFeatureSuiteWithFormatter)
|
||||||
s.Step(`^a feature "([^"]*)" file:$`, c.aFeatureFile)
|
s.Step(`^a feature "([^"]*)" file:$`, c.aFeatureFile)
|
||||||
s.Step(`^the suite should have (passed|failed)$`, c.theSuiteShouldHave)
|
s.Step(`^the suite should have (passed|failed)$`, c.theSuiteShouldHave)
|
||||||
|
|
||||||
|
@ -32,6 +35,9 @@ func SuiteContext(s *Suite) {
|
||||||
s.Step(`^the following steps? should be (passed|failed|skipped|undefined|pending):`, c.followingStepsShouldHave)
|
s.Step(`^the following steps? should be (passed|failed|skipped|undefined|pending):`, c.followingStepsShouldHave)
|
||||||
s.Step(`^the undefined step snippets should be:$`, c.theUndefinedStepSnippetsShouldBe)
|
s.Step(`^the undefined step snippets should be:$`, c.theUndefinedStepSnippetsShouldBe)
|
||||||
|
|
||||||
|
// event stream
|
||||||
|
s.Step(`^the following events should be fired:$`, c.thereShouldBeEventsFired)
|
||||||
|
|
||||||
// lt
|
// lt
|
||||||
s.Step(`^savybių aplankas "([^"]*)"$`, c.featurePath)
|
s.Step(`^savybių aplankas "([^"]*)"$`, c.featurePath)
|
||||||
s.Step(`^aš išskaitau savybes$`, c.parseFeatures)
|
s.Step(`^aš išskaitau savybes$`, c.parseFeatures)
|
||||||
|
@ -54,20 +60,59 @@ type suiteContext struct {
|
||||||
paths []string
|
paths []string
|
||||||
testedSuite *Suite
|
testedSuite *Suite
|
||||||
events []*firedEvent
|
events []*firedEvent
|
||||||
fmt *testFormatter
|
out bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *suiteContext) ResetBeforeEachScenario(interface{}) {
|
func (s *suiteContext) ResetBeforeEachScenario(interface{}) {
|
||||||
// reset whole suite with the state
|
// reset whole suite with the state
|
||||||
s.fmt = &testFormatter{}
|
s.out.Reset()
|
||||||
s.paths = []string{}
|
s.paths = []string{}
|
||||||
s.testedSuite = &Suite{fmt: s.fmt}
|
s.testedSuite = &Suite{}
|
||||||
// our tested suite will have the same context registered
|
// our tested suite will have the same context registered
|
||||||
SuiteContext(s.testedSuite)
|
SuiteContext(s.testedSuite)
|
||||||
// reset all fired events
|
// reset all fired events
|
||||||
s.events = []*firedEvent{}
|
s.events = []*firedEvent{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error {
|
||||||
|
f, err := findFmt(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.testedSuite.fmt = f(&s.out)
|
||||||
|
if err := s.parseFeatures(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.testedSuite.run()
|
||||||
|
s.testedSuite.fmt.Summary()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *suiteContext) thereShouldBeEventsFired(doc *gherkin.DocString) error {
|
||||||
|
actual := strings.Split(strings.TrimSpace(s.out.String()), "\n")
|
||||||
|
expect := strings.Split(strings.TrimSpace(doc.Content), "\n")
|
||||||
|
if len(expect) != len(actual) {
|
||||||
|
return fmt.Errorf("expected %d events, but got %d", len(expect), len(actual))
|
||||||
|
}
|
||||||
|
|
||||||
|
type ev struct {
|
||||||
|
Event string
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, event := range actual {
|
||||||
|
exp := strings.TrimSpace(expect[i])
|
||||||
|
var act ev
|
||||||
|
if err := json.Unmarshal([]byte(event), &act); err != nil {
|
||||||
|
return fmt.Errorf("failed to read event data: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if act.Event != exp {
|
||||||
|
return fmt.Errorf(`expected event: "%s" at position: %d, but actual was "%s"`, exp, i, act.Event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *suiteContext) cleanupSnippet(snip string) string {
|
func (s *suiteContext) cleanupSnippet(snip string) string {
|
||||||
lines := strings.Split(strings.TrimSpace(snip), "\n")
|
lines := strings.Split(strings.TrimSpace(snip), "\n")
|
||||||
for i := 0; i < len(lines); i++ {
|
for i := 0; i < len(lines); i++ {
|
||||||
|
@ -77,10 +122,14 @@ func (s *suiteContext) cleanupSnippet(snip string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *suiteContext) theUndefinedStepSnippetsShouldBe(body *gherkin.DocString) error {
|
func (s *suiteContext) theUndefinedStepSnippetsShouldBe(body *gherkin.DocString) error {
|
||||||
actual := s.cleanupSnippet(s.fmt.snippets())
|
f, ok := s.testedSuite.fmt.(*testFormatter)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("this step requires testFormatter, but there is: %T", s.testedSuite.fmt)
|
||||||
|
}
|
||||||
|
actual := s.cleanupSnippet(f.snippets())
|
||||||
expected := s.cleanupSnippet(body.Content)
|
expected := s.cleanupSnippet(body.Content)
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
return fmt.Errorf("snippets do not match actual: %s", s.fmt.snippets())
|
return fmt.Errorf("snippets do not match actual: %s", f.snippets())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -89,25 +138,29 @@ func (s *suiteContext) followingStepsShouldHave(status string, steps *gherkin.Do
|
||||||
var expected = strings.Split(steps.Content, "\n")
|
var expected = strings.Split(steps.Content, "\n")
|
||||||
var actual, unmatched, matched []string
|
var actual, unmatched, matched []string
|
||||||
|
|
||||||
|
f, ok := s.testedSuite.fmt.(*testFormatter)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("this step requires testFormatter, but there is: %T", s.testedSuite.fmt)
|
||||||
|
}
|
||||||
switch status {
|
switch status {
|
||||||
case "passed":
|
case "passed":
|
||||||
for _, st := range s.fmt.passed {
|
for _, st := range f.passed {
|
||||||
actual = append(actual, st.step.Text)
|
actual = append(actual, st.step.Text)
|
||||||
}
|
}
|
||||||
case "failed":
|
case "failed":
|
||||||
for _, st := range s.fmt.failed {
|
for _, st := range f.failed {
|
||||||
actual = append(actual, st.step.Text)
|
actual = append(actual, st.step.Text)
|
||||||
}
|
}
|
||||||
case "skipped":
|
case "skipped":
|
||||||
for _, st := range s.fmt.skipped {
|
for _, st := range f.skipped {
|
||||||
actual = append(actual, st.step.Text)
|
actual = append(actual, st.step.Text)
|
||||||
}
|
}
|
||||||
case "undefined":
|
case "undefined":
|
||||||
for _, st := range s.fmt.undefined {
|
for _, st := range f.undefined {
|
||||||
actual = append(actual, st.step.Text)
|
actual = append(actual, st.step.Text)
|
||||||
}
|
}
|
||||||
case "pending":
|
case "pending":
|
||||||
for _, st := range s.fmt.pending {
|
for _, st := range f.pending {
|
||||||
actual = append(actual, st.step.Text)
|
actual = append(actual, st.step.Text)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -231,7 +284,9 @@ func (s *suiteContext) iRunFeatureSuite() error {
|
||||||
if err := s.parseFeatures(); err != nil {
|
if err := s.parseFeatures(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
s.testedSuite.fmt = testFormatterFunc(&s.out)
|
||||||
s.testedSuite.run()
|
s.testedSuite.run()
|
||||||
|
s.testedSuite.fmt.Summary()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче