some necessary command line options
Этот коммит содержится в:
		
							родитель
							
								
									cb47b27090
								
							
						
					
					
						коммит
						a3ef3361f8
					
				
					 6 изменённых файлов: 115 добавлений и 16 удалений
				
			
		
							
								
								
									
										15
									
								
								config.go
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								config.go
									
										
									
									
									
								
							|  | @ -41,6 +41,11 @@ func init() { | ||||||
| 
 | 
 | ||||||
| 	flag.StringVar(&cfg.format, "format", "pretty", "") | 	flag.StringVar(&cfg.format, "format", "pretty", "") | ||||||
| 	flag.StringVar(&cfg.format, "f", "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() { | 	flag.Usage = func() { | ||||||
| 		// prints an option or argument with a description, or only description | 		// prints an option or argument with a description, or only description | ||||||
| 		opt := func(name, desc string) string { | 		opt := func(name, desc string) string { | ||||||
|  | @ -66,11 +71,17 @@ func init() { | ||||||
| 
 | 
 | ||||||
| 		// --- OPTIONS --- | 		// --- OPTIONS --- | ||||||
| 		fmt.Println(cl("Options:", yellow)) | 		fmt.Println(cl("Options:", yellow)) | ||||||
|  | 		// --> step definitions | ||||||
|  | 		fmt.Println(opt("-d, --definitions", "Print all available step definitions.")) | ||||||
| 		// --> format | 		// --> format | ||||||
| 		fmt.Println(opt("-f, --format=pretty", "How to format tests output. Available formats:")) | 		fmt.Println(opt("-f, --format=pretty", "How to format tests output. Available formats:")) | ||||||
| 		for _, f := range formatters { | 		for _, f := range formatters { | ||||||
| 			fmt.Println(opt("", s(4)+"- "+cl(f.name, yellow)+": "+f.description)) | 			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("") | 		fmt.Println("") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -78,6 +89,10 @@ func init() { | ||||||
| type config struct { | type config struct { | ||||||
| 	paths  []string | 	paths  []string | ||||||
| 	format string | 	format string | ||||||
|  | 
 | ||||||
|  | 	definitions   bool | ||||||
|  | 	stopOnFailure bool | ||||||
|  | 	version       bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *config) validate() error { | func (c *config) validate() error { | ||||||
|  |  | ||||||
|  | @ -6,4 +6,12 @@ Feature: suite hooks | ||||||
|   Background: |   Background: | ||||||
|     Given I have a before scenario hook |     Given I have a before scenario hook | ||||||
|     And a feature path "features/load_features.feature:6" |     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 | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								formatter.go
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								formatter.go
									
										
									
									
									
								
							|  | @ -89,10 +89,16 @@ func (f *pretty) line(tok *gherkin.Token) string { | ||||||
| 
 | 
 | ||||||
| // checks whether it should not print a background step once again | // checks whether it should not print a background step once again | ||||||
| func (f *pretty) canPrintStep(step *gherkin.Step) bool { | func (f *pretty) canPrintStep(step *gherkin.Step) bool { | ||||||
| 	if f.background != nil { | 	if f.background == nil { | ||||||
| 		return step.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 | // 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(bcl("Feature: ", white) + t.Title) | ||||||
| 		fmt.Println(t.Description) | 		fmt.Println(t.Description) | ||||||
| 	case *gherkin.Background: | 	case *gherkin.Background: | ||||||
| 		f.background = t | 		// determine comment position based on step length | ||||||
| 		fmt.Println("\n" + bcl("Background:", white)) | 		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: | 	case *gherkin.Scenario: | ||||||
|  | 		// determine comment position based on step length | ||||||
| 		f.commentPos = len(t.Token.Text) | 		f.commentPos = len(t.Token.Text) | ||||||
| 		for _, step := range t.Steps { | 		for _, step := range t.Steps { | ||||||
| 			if len(step.Token.Text) > f.commentPos { | 			if len(step.Token.Text) > f.commentPos { | ||||||
|  | @ -187,9 +204,6 @@ func (f *pretty) Summary() { | ||||||
| 
 | 
 | ||||||
| // prints a single matched step | // prints a single matched step | ||||||
| func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c color) { | func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c color) { | ||||||
| 	if !f.canPrintStep(step) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	var text string | 	var text string | ||||||
| 	if m := (match.expr.FindStringSubmatchIndex(step.Text))[2:]; len(m) > 0 { | 	if m := (match.expr.FindStringSubmatchIndex(step.Text))[2:]; len(m) > 0 { | ||||||
| 		var pos, i int | 		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 | // Passed is called to represent a passed step | ||||||
| func (f *pretty) Passed(step *gherkin.Step, match *stepMatchHandler) { | 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}) | 	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 | // Failed is called to represent a failed step | ||||||
| func (f *pretty) Failed(step *gherkin.Step, match *stepMatchHandler, err error) { | func (f *pretty) Failed(step *gherkin.Step, match *stepMatchHandler, err error) { | ||||||
| 	f.printMatchedStep(step, match, red) | 	if f.canPrintStep(step) { | ||||||
| 	fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red)) | 		f.printMatchedStep(step, match, red) | ||||||
|  | 		fmt.Println(strings.Repeat(" ", step.Token.Indent) + bcl(err, red)) | ||||||
|  | 	} | ||||||
| 	f.failed = append(f.failed, &failed{step, err}) | 	f.failed = append(f.failed, &failed{step, err}) | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								godog.go
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								godog.go
									
										
									
									
									
								
							|  | @ -33,3 +33,5 @@ As you’ll 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. | Godog was inspired by Behat and the above description is taken from it's documentation. | ||||||
| */ | */ | ||||||
| package godog | package godog | ||||||
|  | 
 | ||||||
|  | const Version = "v0.1.0-alpha" | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								suite.go
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								suite.go
									
										
									
									
									
								
							|  | @ -3,7 +3,9 @@ package godog | ||||||
| import ( | import ( | ||||||
| 	"flag" | 	"flag" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
| 	"regexp" | 	"regexp" | ||||||
|  | 	"runtime" | ||||||
| 
 | 
 | ||||||
| 	"github.com/DATA-DOG/godog/gherkin" | 	"github.com/DATA-DOG/godog/gherkin" | ||||||
| ) | ) | ||||||
|  | @ -63,6 +65,8 @@ type suite struct { | ||||||
| 	stepHandlers           []*stepMatchHandler | 	stepHandlers           []*stepMatchHandler | ||||||
| 	features               []*gherkin.Feature | 	features               []*gherkin.Feature | ||||||
| 	fmt                    Formatter | 	fmt                    Formatter | ||||||
|  | 
 | ||||||
|  | 	stop bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New initializes a suite which supports the Suite | // New initializes a suite which supports the Suite | ||||||
|  | @ -99,14 +103,29 @@ func (s *suite) Run() { | ||||||
| 	if !flag.Parsed() { | 	if !flag.Parsed() { | ||||||
| 		flag.Parse() | 		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.fmt = cfg.formatter() | ||||||
| 	s.features, err = cfg.features() | 	s.features, err = cfg.features() | ||||||
| 	fatal(err) | 	fatal(err) | ||||||
| 
 | 
 | ||||||
| 	for _, f := range s.features { | 	for _, f := range s.features { | ||||||
| 		s.runFeature(f) | 		s.runFeature(f) | ||||||
|  | 		if s.stop { | ||||||
|  | 			// stop on first failure | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	s.fmt.Summary() | 	s.fmt.Summary() | ||||||
| } | } | ||||||
|  | @ -171,14 +190,16 @@ func (s *suite) skipSteps(steps []*gherkin.Step) { | ||||||
| 
 | 
 | ||||||
| func (s *suite) runFeature(f *gherkin.Feature) { | func (s *suite) runFeature(f *gherkin.Feature) { | ||||||
| 	s.fmt.Node(f) | 	s.fmt.Node(f) | ||||||
| 	var failed bool |  | ||||||
| 	for _, scenario := range f.Scenarios { | 	for _, scenario := range f.Scenarios { | ||||||
|  | 		var failed bool | ||||||
|  | 
 | ||||||
| 		// run before scenario handlers | 		// run before scenario handlers | ||||||
| 		for _, h := range s.beforeScenarioHandlers { | 		for _, h := range s.beforeScenarioHandlers { | ||||||
| 			h.BeforeScenario(scenario) | 			h.BeforeScenario(scenario) | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		// background | 		// background | ||||||
| 		if f.Background != nil && !failed { | 		if f.Background != nil { | ||||||
| 			s.fmt.Node(f.Background) | 			s.fmt.Node(f.Background) | ||||||
| 			failed = s.runSteps(f.Background.Steps) | 			failed = s.runSteps(f.Background.Steps) | ||||||
| 		} | 		} | ||||||
|  | @ -188,7 +209,28 @@ func (s *suite) runFeature(f *gherkin.Feature) { | ||||||
| 		if failed { | 		if failed { | ||||||
| 			s.skipSteps(scenario.Steps) | 			s.skipSteps(scenario.Steps) | ||||||
| 		} else { | 		} 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 { | type suiteFeature struct { | ||||||
| 	suite | 	suite | ||||||
|  | 	// for hook tests | ||||||
|  | 	befScenarioHook *gherkin.Scenario | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *suiteFeature) BeforeScenario(scenario *gherkin.Scenario) { | func (s *suiteFeature) BeforeScenario(scenario *gherkin.Scenario) { | ||||||
| 	// reset feature paths | 	// reset feature paths | ||||||
| 	cfg.paths = []string{} | 	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 { | func (s *suiteFeature) featurePath(args ...*Arg) error { | ||||||
|  | @ -63,4 +74,7 @@ func SuiteContext(g Suite) { | ||||||
| 	g.Step( | 	g.Step( | ||||||
| 		regexp.MustCompile(`^I should have ([\d]+) scenarios? registered$`), | 		regexp.MustCompile(`^I should have ([\d]+) scenarios? registered$`), | ||||||
| 		StepHandlerFunc(s.numScenariosRegistered)) | 		StepHandlerFunc(s.numScenariosRegistered)) | ||||||
|  | 	g.Step( | ||||||
|  | 		regexp.MustCompile(`^I have a before scenario hook$`), | ||||||
|  | 		StepHandlerFunc(s.iHaveBeforeScenarioHook)) | ||||||
| } | } | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 gedi
						gedi