Этот коммит содержится в:
gedi 2015-06-19 10:30:38 +03:00
родитель 1f4ac0e8ec
коммит c604d39ac5
5 изменённых файлов: 101 добавлений и 54 удалений

Просмотреть файл

@ -7,12 +7,12 @@ Feature: suite events
Given I'm listening to suite events
Scenario: triggers before scenario event
Given a feature path "features/load_features.feature:6"
Given a feature path "features/load.feature:6"
When I run feature suite
Then there was event triggered before scenario "load features within path"
Scenario: triggers appropriate events for a single scenario
Given a feature path "features/load_features.feature:6"
Given a feature path "features/load.feature:6"
When I run feature suite
Then these events had to be fired for a number of times:
| BeforeSuite | 1 |
@ -23,7 +23,7 @@ Feature: suite events
| AfterSuite | 1 |
Scenario: triggers appropriate events whole feature
Given a feature path "features/load_features.feature"
Given a feature path "features/load.feature"
When I run feature suite
Then these events had to be fired for a number of times:
| BeforeSuite | 1 |

Просмотреть файл

@ -6,31 +6,32 @@ Feature: load features
Scenario: load features within path
Given a feature path "features"
When I parse features
Then I should have 2 feature files:
Then I should have 3 feature files:
"""
features/events.feature
features/load_features.feature
features/load.feature
features/run.feature
"""
Scenario: load a specific feature file
Given a feature path "features/load_features.feature"
Given a feature path "features/load.feature"
When I parse features
Then I should have 1 feature file:
"""
features/load_features.feature
features/load.feature
"""
Scenario: load a feature file with a specified scenario
Given a feature path "features/load_features.feature:6"
Given a feature path "features/load.feature:6"
When I parse features
Then I should have 1 scenario registered
Scenario: load a number of feature files
Given a feature path "features/load_features.feature"
Given a feature path "features/load.feature"
And a feature path "features/events.feature"
When I parse features
Then I should have 2 feature files:
"""
features/load_features.feature
features/load.feature
features/events.feature
"""

18
features/run.feature Обычный файл
Просмотреть файл

@ -0,0 +1,18 @@
Feature: run features
In order to test application behavior
As a test suite
I need to be able to run features
Scenario: should run a normal feature
Given a feature "normal.feature" file:
"""
Feature: normal feature
Scenario: parse a scenario
Given a feature path "features/load.feature:6"
When I parse features
Then I should have 1 scenario registered
"""
When I run feature suite
Then the suite should have passed successfully

Просмотреть файл

@ -11,12 +11,21 @@ import (
"github.com/DATA-DOG/godog/gherkin"
)
// Regexp is an unified type for regular expression
// it can be either a string or a *regexp.Regexp
type Regexp interface{}
// Handler is an unified type for a StepHandler
// interface satisfaction. It may be a function
// or a step handler
type Handler interface{}
// Status represents a step or scenario status
type Status int
// step or scenario status constants
const (
invalid Status = iota
Invalid Status = iota
Passed
Failed
Undefined
@ -71,7 +80,7 @@ type stepMatchHandler struct {
// Suite is an interface which allows various contexts
// to register step definitions and event handlers
type Suite interface {
Step(expr *regexp.Regexp, h StepHandler)
Step(expr Regexp, h Handler)
// suite events
BeforeSuite(h BeforeSuiteHandler)
BeforeScenario(h BeforeScenarioHandler)
@ -106,7 +115,10 @@ func New() *suite {
// Step allows to register a StepHandler in Godog
// feature suite, the handler will be applied to all
// steps matching the given regexp
// steps matching the given regexp expr
//
// It will panic if expr is not a valid regular expression
// or handler does not satisfy StepHandler interface
//
// Note that if there are two handlers which may match
// the same step, then the only first matched handler
@ -114,10 +126,34 @@ func New() *suite {
//
// If none of the StepHandlers are matched, then a pending
// step error will be raised.
func (s *suite) Step(expr *regexp.Regexp, h StepHandler) {
func (s *suite) Step(expr Regexp, h Handler) {
var handler StepHandler
var regex *regexp.Regexp
switch t := expr.(type) {
case *regexp.Regexp:
regex = t
case string:
regex = regexp.MustCompile(t)
case []byte:
regex = regexp.MustCompile(string(t))
default:
panic(fmt.Sprintf("expecting expr to be a *regexp.Regexp or a string, got type: %T", expr))
}
switch t := h.(type) {
case StepHandlerFunc:
handler = t
case StepHandler:
handler = t
case func(...*Arg) error:
handler = StepHandlerFunc(t)
default:
panic(fmt.Sprintf("expecting handler to satisfy StepHandler interface, got type: %T", h))
}
s.stepHandlers = append(s.stepHandlers, &stepMatchHandler{
handler: h,
expr: expr,
handler: handler,
expr: regex,
})
}
@ -304,7 +340,7 @@ func (s *suite) runFeature(f *gherkin.Feature) {
s.skipSteps(scenario.Steps)
case status == Undefined:
s.skipSteps(scenario.Steps)
case status == Passed || status == invalid:
case status == Passed || status == Invalid:
status = s.runSteps(scenario.Steps)
}

Просмотреть файл

@ -2,8 +2,6 @@ package godog
import (
"fmt"
"os"
"regexp"
"strings"
"github.com/DATA-DOG/godog/gherkin"
@ -15,9 +13,8 @@ type firedEvent struct {
}
type suiteFeature struct {
testedSuite *suite
events []*firedEvent
tempFeatures []string
testedSuite *suite
events []*firedEvent
}
func (s *suiteFeature) HandleBeforeScenario(*gherkin.Scenario) {
@ -27,18 +24,10 @@ func (s *suiteFeature) HandleBeforeScenario(*gherkin.Scenario) {
SuiteContext(s.testedSuite)
// reset feature paths
cfg.paths = []string{}
s.tempFeatures = []string{}
// reset all fired events
s.events = []*firedEvent{}
}
func (s *suiteFeature) HandleAfterScenario(*gherkin.Scenario) {
// remove temp files
for _, f := range s.tempFeatures {
os.Remove("/tmp/" + f)
}
}
func (s *suiteFeature) iAmListeningToSuiteEvents(args ...*Arg) error {
s.testedSuite.BeforeSuite(BeforeSuiteHandlerFunc(func() {
s.events = append(s.events, &firedEvent{"BeforeSuite", []interface{}{}})
@ -65,8 +54,13 @@ func (s *suiteFeature) aFailingStep(...*Arg) error {
return fmt.Errorf("intentional failure")
}
func (s *suiteFeature) tempFeatureFile(args ...*Arg) error {
return nil
// parse a given feature file body as a feature
func (s *suiteFeature) aFeatureFile(args ...*Arg) error {
name := args[0].String()
body := args[1].PyString().Raw
feature, err := gherkin.Parse(strings.NewReader(body), name)
s.testedSuite.features = append(s.testedSuite.features, feature)
return err
}
func (s *suiteFeature) featurePath(args ...*Arg) error {
@ -79,6 +73,13 @@ func (s *suiteFeature) parseFeatures(args ...*Arg) (err error) {
return
}
func (s *suiteFeature) theSuitePassedSuccessfully(...*Arg) error {
if s.testedSuite.failed {
return fmt.Errorf("the feature suite has failed")
}
return nil
}
func (s *suiteFeature) iShouldHaveNumFeatureFiles(args ...*Arg) error {
if len(s.testedSuite.features) != args[0].Int() {
return fmt.Errorf("expected %d features to be parsed, but have %d", args[0].Int(), len(s.testedSuite.features))
@ -177,28 +178,19 @@ func SuiteContext(g Suite) {
g.BeforeScenario(s)
g.Step(regexp.MustCompile(`^a feature path "([^"]*)"$`), StepHandlerFunc(s.featurePath))
g.Step(regexp.MustCompile(`^I parse features$`), StepHandlerFunc(s.parseFeatures))
g.Step(regexp.MustCompile(`^I'm listening to suite events$`), StepHandlerFunc(s.iAmListeningToSuiteEvents))
g.Step(regexp.MustCompile(`^I run feature suite$`), StepHandlerFunc(s.iRunFeatureSuite))
g.Step(regexp.MustCompile(`^feature "([^"]*)" file:$`), StepHandlerFunc(s.tempFeatureFile))
g.Step(`^a feature path "([^"]*)"$`, s.featurePath)
g.Step(`^I parse features$`, s.parseFeatures)
g.Step(`^I'm listening to suite events$`, s.iAmListeningToSuiteEvents)
g.Step(`^I run feature suite$`, s.iRunFeatureSuite)
g.Step(`^a feature "([^"]*)" file:$`, s.aFeatureFile)
g.Step(`^the suite should have passed successfully$`, s.theSuitePassedSuccessfully)
g.Step(
regexp.MustCompile(`^I should have ([\d]+) features? files?:$`),
StepHandlerFunc(s.iShouldHaveNumFeatureFiles))
g.Step(
regexp.MustCompile(`^I should have ([\d]+) scenarios? registered$`),
StepHandlerFunc(s.numScenariosRegistered))
g.Step(
regexp.MustCompile(`^there (was|were) ([\d]+) "([^"]*)" events? fired$`),
StepHandlerFunc(s.thereWereNumEventsFired))
g.Step(
regexp.MustCompile(`^there was event triggered before scenario "([^"]*)"$`),
StepHandlerFunc(s.thereWasEventTriggeredBeforeScenario))
g.Step(
regexp.MustCompile(`^these events had to be fired for a number of times:$`),
StepHandlerFunc(s.theseEventsHadToBeFiredForNumberOfTimes))
g.Step(`^I should have ([\d]+) features? files?:$`, s.iShouldHaveNumFeatureFiles)
g.Step(`^I should have ([\d]+) scenarios? registered$`, s.numScenariosRegistered)
g.Step(`^there (was|were) ([\d]+) "([^"]*)" events? fired$`, s.thereWereNumEventsFired)
g.Step(`^there was event triggered before scenario "([^"]*)"$`, s.thereWasEventTriggeredBeforeScenario)
g.Step(`^these events had to be fired for a number of times:$`, s.theseEventsHadToBeFiredForNumberOfTimes)
g.Step(regexp.MustCompile(`^a failing step`), StepHandlerFunc(s.aFailingStep))
g.Step(regexp.MustCompile(`^this step should fail`), StepHandlerFunc(s.aFailingStep))
g.Step(`^a failing step`, s.aFailingStep)
g.Step(`^this step should fail`, s.aFailingStep)
}