some necessary command line options

Этот коммит содержится в:
gedi 2015-06-17 16:44:42 +03:00
родитель cb47b27090
коммит a3ef3361f8
6 изменённых файлов: 115 добавлений и 16 удалений

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

@ -41,6 +41,11 @@ func init() {
flag.StringVar(&cfg.format, "format", "pretty", "")
flag.StringVar(&cfg.format, "f", "pretty", "")
flag.BoolVar(&cfg.definitions, "definitions", false, "")
flag.BoolVar(&cfg.definitions, "d", false, "")
flag.BoolVar(&cfg.stopOnFailure, "stop-on-failure", false, "")
flag.BoolVar(&cfg.version, "version", false, "")
flag.Usage = func() {
// prints an option or argument with a description, or only description
opt := func(name, desc string) string {
@ -66,11 +71,17 @@ func init() {
// --- OPTIONS ---
fmt.Println(cl("Options:", yellow))
// --> step definitions
fmt.Println(opt("-d, --definitions", "Print all available step definitions."))
// --> format
fmt.Println(opt("-f, --format=pretty", "How to format tests output. Available formats:"))
for _, f := range formatters {
fmt.Println(opt("", s(4)+"- "+cl(f.name, yellow)+": "+f.description))
}
// --> stop on failure
fmt.Println(opt("--stop-on-failure", "Stop processing on first failed scenario."))
// --> version
fmt.Println(opt("--version", "Show current "+cl("godog", yellow)+" version."))
fmt.Println("")
}
}
@ -78,6 +89,10 @@ func init() {
type config struct {
paths []string
format string
definitions bool
stopOnFailure bool
version bool
}
func (c *config) validate() error {

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

@ -6,4 +6,12 @@ Feature: suite hooks
Background:
Given I have a before scenario hook
And a feature path "features/load_features.feature:6"
# When I parse and run features
And I parse features
Scenario: hi there
When I run features
Then I should have a scenario "" recorded in the hook
Scenario: and there
When I run features
Then I should have a scenario "" recorded in the hook

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

@ -89,10 +89,16 @@ func (f *pretty) line(tok *gherkin.Token) string {
// checks whether it should not print a background step once again
func (f *pretty) canPrintStep(step *gherkin.Step) bool {
if f.background != nil {
return step.Background != nil
if f.background == nil {
return true
}
return true
if step.Background == nil {
f.doneBackground = true
return true
}
return !f.doneBackground
}
// Node takes a gherkin node for formatting
@ -110,9 +116,20 @@ func (f *pretty) Node(node interface{}) {
fmt.Println(bcl("Feature: ", white) + t.Title)
fmt.Println(t.Description)
case *gherkin.Background:
f.background = t
fmt.Println("\n" + bcl("Background:", white))
// determine comment position based on step length
f.commentPos = len(t.Token.Text)
for _, step := range t.Steps {
if len(step.Token.Text) > f.commentPos {
f.commentPos = len(step.Token.Text)
}
}
// do not repeat background
if !f.doneBackground {
f.background = t
fmt.Println("\n" + strings.Repeat(" ", t.Token.Indent) + bcl("Background:", white))
}
case *gherkin.Scenario:
// determine comment position based on step length
f.commentPos = len(t.Token.Text)
for _, step := range t.Steps {
if len(step.Token.Text) > f.commentPos {
@ -187,9 +204,6 @@ func (f *pretty) Summary() {
// prints a single matched step
func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c color) {
if !f.canPrintStep(step) {
return
}
var text string
if m := (match.expr.FindStringSubmatchIndex(step.Text))[2:]; len(m) > 0 {
var pos, i int
@ -228,7 +242,9 @@ func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c
// Passed is called to represent a passed step
func (f *pretty) Passed(step *gherkin.Step, match *stepMatchHandler) {
f.printMatchedStep(step, match, green)
if f.canPrintStep(step) {
f.printMatchedStep(step, match, green)
}
f.passed = append(f.passed, &passed{step})
}
@ -250,7 +266,9 @@ func (f *pretty) Undefined(step *gherkin.Step) {
// Failed is called to represent a failed step
func (f *pretty) Failed(step *gherkin.Step, match *stepMatchHandler, err error) {
f.printMatchedStep(step, match, red)
fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red))
if f.canPrintStep(step) {
f.printMatchedStep(step, match, red)
fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red))
}
f.failed = append(f.failed, &failed{step, err})
}

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

@ -33,3 +33,5 @@ As youll see, Godog is easy to learn, quick to use, and will put the fun back
Godog was inspired by Behat and the above description is taken from it's documentation.
*/
package godog
const Version = "v0.1.0-alpha"

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

@ -3,7 +3,9 @@ package godog
import (
"flag"
"fmt"
"reflect"
"regexp"
"runtime"
"github.com/DATA-DOG/godog/gherkin"
)
@ -63,6 +65,8 @@ type suite struct {
stepHandlers []*stepMatchHandler
features []*gherkin.Feature
fmt Formatter
stop bool
}
// New initializes a suite which supports the Suite
@ -99,14 +103,29 @@ func (s *suite) Run() {
if !flag.Parsed() {
flag.Parse()
}
fatal(cfg.validate())
// check if we need to just show something first
switch {
case cfg.version:
fmt.Println(cl("Godog", green) + " version is " + cl(Version, yellow))
return
case cfg.definitions:
s.printStepDefinitions()
return
}
// run a feature suite
fatal(cfg.validate())
s.fmt = cfg.formatter()
s.features, err = cfg.features()
fatal(err)
for _, f := range s.features {
s.runFeature(f)
if s.stop {
// stop on first failure
break
}
}
s.fmt.Summary()
}
@ -171,14 +190,16 @@ func (s *suite) skipSteps(steps []*gherkin.Step) {
func (s *suite) runFeature(f *gherkin.Feature) {
s.fmt.Node(f)
var failed bool
for _, scenario := range f.Scenarios {
var failed bool
// run before scenario handlers
for _, h := range s.beforeScenarioHandlers {
h.BeforeScenario(scenario)
}
// background
if f.Background != nil && !failed {
if f.Background != nil {
s.fmt.Node(f.Background)
failed = s.runSteps(f.Background.Steps)
}
@ -188,7 +209,28 @@ func (s *suite) runFeature(f *gherkin.Feature) {
if failed {
s.skipSteps(scenario.Steps)
} else {
s.runSteps(scenario.Steps)
failed = s.runSteps(scenario.Steps)
}
if failed && cfg.stopOnFailure {
s.stop = true
return
}
}
}
func (st *suite) printStepDefinitions() {
var longest int
for _, def := range st.stepHandlers {
if longest < len(def.expr.String()) {
longest = len(def.expr.String())
}
}
for _, def := range st.stepHandlers {
location := runtime.FuncForPC(reflect.ValueOf(def.handler).Pointer()).Name()
fmt.Println(cl(def.expr.String(), yellow)+s(longest-len(def.expr.String())), cl("# "+location, black))
}
if len(st.stepHandlers) == 0 {
fmt.Println("there were no contexts registered, could not find any step definition..")
}
}

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

@ -9,11 +9,22 @@ import (
type suiteFeature struct {
suite
// for hook tests
befScenarioHook *gherkin.Scenario
}
func (s *suiteFeature) BeforeScenario(scenario *gherkin.Scenario) {
// reset feature paths
cfg.paths = []string{}
// reset hook test references
s.befScenarioHook = nil
}
func (s *suiteFeature) iHaveBeforeScenarioHook(args ...*Arg) error {
s.suite.BeforeScenario(BeforeScenarioHandlerFunc(func(scenario *gherkin.Scenario) {
s.befScenarioHook = scenario
}))
return nil
}
func (s *suiteFeature) featurePath(args ...*Arg) error {
@ -63,4 +74,7 @@ func SuiteContext(g Suite) {
g.Step(
regexp.MustCompile(`^I should have ([\d]+) scenarios? registered$`),
StepHandlerFunc(s.numScenariosRegistered))
g.Step(
regexp.MustCompile(`^I have a before scenario hook$`),
StepHandlerFunc(s.iHaveBeforeScenarioHook))
}