From fa9419c2d3e07ae4f8119c3b70205324610597e2 Mon Sep 17 00:00:00 2001 From: gedi Date: Sat, 13 Jun 2015 00:02:10 +0300 Subject: [PATCH] start to describing godog itself with godog --- builder.go | 16 +++++--- features/suite.feature | 9 +++++ gherkin/example/ls_test.go | 28 ------------- suite.go | 80 ++++++++++++++++++++++++++++++++++++-- suite_test.go | 45 +++++++++++++++++++++ 5 files changed, 141 insertions(+), 37 deletions(-) create mode 100644 features/suite.feature delete mode 100644 gherkin/example/ls_test.go create mode 100644 suite_test.go diff --git a/builder.go b/builder.go index f0db029..d04f4bd 100644 --- a/builder.go +++ b/builder.go @@ -18,6 +18,7 @@ type builder struct { files map[string]*ast.File fset *token.FileSet Contexts []string + Internal bool tpl *template.Template } @@ -26,15 +27,14 @@ func newBuilder() *builder { files: make(map[string]*ast.File), fset: token.NewFileSet(), tpl: template.Must(template.New("main").Parse(`package main - -import ( +{{ if not .Internal }}import ( "github.com/DATA-DOG/godog" -) +){{ end }} func main() { - suite := godog.New() - {{range $c := .Contexts}} - {{$c}}(suite) + suite := {{ if not .Internal }}godog.{{ end }}New() + {{range .Contexts}} + {{ . }}(suite) {{end}} suite.Run() }`)), @@ -46,6 +46,10 @@ func (b *builder) parseFile(path string) error { if err != nil { return err } + // mark godog package as internal + if f.Name.Name == "godog" && !b.Internal { + b.Internal = true + } b.deleteMainFunc(f) b.registerSteps(f) b.deleteImports(f) diff --git a/features/suite.feature b/features/suite.feature new file mode 100644 index 0000000..59db83d --- /dev/null +++ b/features/suite.feature @@ -0,0 +1,9 @@ +Feature: godog bdd suite + In order to test application behavior + As a suite + I need to be able to register and run features + + Scenario: + Given a feature path "features" + When I parse features + Then I should have 1 feature file diff --git a/gherkin/example/ls_test.go b/gherkin/example/ls_test.go deleted file mode 100644 index e46ed19..0000000 --- a/gherkin/example/ls_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "regexp" - - "github.com/DATA-DOG/godog" -) - -type lsFeature struct{} - -func (s *lsFeature) inDirectory(args ...godog.Arg) error { - return nil -} - -func (s *lsFeature) haveFile(args ...godog.Arg) error { - return nil -} - -func SuiteContext(g godog.Suite) { - f := &lsFeature{} - - g.Step( - regexp.MustCompile(`^I am in a directory "([^"]*)"$`), - godog.StepHandlerFunc(f.inDirectory)) - g.Step( - regexp.MustCompile(`^I have a file named "([^"]*)"$`), - godog.StepHandlerFunc(f.haveFile)) -} diff --git a/suite.go b/suite.go index d27e614..f0cf633 100644 --- a/suite.go +++ b/suite.go @@ -13,14 +13,29 @@ import ( // the regexp submatch to handle the step type Arg string -// Float converts an argument to float64 value -// or panics if it does not know how to convert it +// Float converts an argument to float64 +// or panics if unable to convert it func (a Arg) Float() float64 { v, err := strconv.ParseFloat(string(a), 64) if err == nil { return v } - panic(fmt.Sprintf(`cannot convert string "%s" to float64: %s`, a, err)) + panic(fmt.Sprintf(`cannot convert "%s" to float64: %s`, a, err)) +} + +// Int converts an argument to int64 +// or panics if unable to convert it +func (a Arg) Int() int64 { + v, err := strconv.ParseInt(string(a), 10, 0) + if err == nil { + return v + } + panic(fmt.Sprintf(`cannot convert "%s" to int64: %s`, a, err)) +} + +// String converts an argument to string +func (a Arg) String() string { + return string(a) } // Objects implementing the StepHandler interface can be @@ -97,4 +112,63 @@ func (s *suite) Run() { fmt.Println("running", cl("godog", cyan)+", num registered steps:", cl(len(s.steps), yellow)) fmt.Println("have loaded", cl(len(s.features), yellow), "features from path:", cl(cfg.featuresPath, green)) + + for _, f := range s.features { + s.runFeature(f) + } +} + +func (s *suite) runFeature(f *gherkin.Feature) { + for _, scenario := range f.Scenarios { + if f.Background != nil { + for _, step := range f.Background.Steps { + var handler StepHandler + var args []Arg + for r, h := range s.steps { + if m := r.FindStringSubmatch(step.Text); len(m) > 0 { + handler = h + for _, a := range m[1:] { + args = append(args, Arg(a)) + } + break + } + } + if handler != nil { + if err := handler.HandleStep(args...); err != nil { + // @TODO: scenario fails, step failed + fmt.Println("ERR") + } else { + fmt.Println("OK") + } + // @TODO: handle panic and recover + } else { + fmt.Println("PENDING") + } + } + } + for _, step := range scenario.Steps { + var handler StepHandler + var args []Arg + for r, h := range s.steps { + if m := r.FindStringSubmatch(step.Text); len(m) > 0 { + handler = h + for _, a := range m[1:] { + args = append(args, Arg(a)) + } + break + } + } + if handler != nil { + if err := handler.HandleStep(args...); err != nil { + // @TODO: scenario fails, step failed + fmt.Println("ERR") + } else { + fmt.Println("OK") + } + // @TODO: handle panic and recover + } else { + fmt.Println("PENDING") + } + } + } } diff --git a/suite_test.go b/suite_test.go new file mode 100644 index 0000000..fec0ada --- /dev/null +++ b/suite_test.go @@ -0,0 +1,45 @@ +package godog + +import ( + "fmt" + "regexp" +) + +type suiteFeature struct { + suite +} + +func (s *suiteFeature) featurePath(args ...Arg) error { + cfg.featuresPath = args[0].String() + return nil +} + +func (s *suiteFeature) parseFeatures(args ...Arg) (err error) { + s.features, err = cfg.features() + return +} + +func (s *suiteFeature) numParsed(args ...Arg) (err error) { + if len(s.features) != int(args[0].Int()) { + err = fmt.Errorf("expected %d features to be parsed, but have %d", args[0].Int(), len(s.features)) + } + return +} + +func SuiteContext(g Suite) { + s := &suiteFeature{ + suite: suite{ + steps: make(map[*regexp.Regexp]StepHandler), + }, + } + + 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 should have ([\d]+) features? files?$`), + StepHandlerFunc(s.numParsed)) +}