add an ls feature example
Этот коммит содержится в:
		
							родитель
							
								
									6e65757f89
								
							
						
					
					
						коммит
						e824fde3f9
					
				
					 15 изменённых файлов: 244 добавлений и 100 удалений
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										предоставленный
									
									
								
							|  | @ -1 +1,2 @@ | |||
| /cmd/godog/godog | ||||
| /example/example | ||||
|  |  | |||
|  | @ -9,6 +9,10 @@ describe a feature of your application and how it should work, and only then imp | |||
| 
 | ||||
| The project is inspired by [behat][behat] and [cucumber][cucumber] and is based on cucumber [gherkin specification][gherkin]. | ||||
| 
 | ||||
| ### Install | ||||
| 
 | ||||
|     go install github.com/DATA-DOG/godog/cmd/godog | ||||
| 
 | ||||
| ### Be aware that | ||||
| 
 | ||||
| The work is still in progress and is not functional yet, neither it is intended for production usage. | ||||
|  | @ -21,7 +25,9 @@ See **.travis.yml** for supported **go** versions. | |||
| 
 | ||||
| ### License | ||||
| 
 | ||||
| Licensed under the [three clause BSD license][license] | ||||
| All package dependencies are **MIT** or **BSD** licensed. | ||||
| 
 | ||||
| **Godog** is licensed under the [three clause BSD license][license] | ||||
| 
 | ||||
| [godoc]: http://godoc.org/github.com/DATA-DOG/godog "Documentation on godoc" | ||||
| [godoc_gherkin]: http://godoc.org/github.com/DATA-DOG/godog/gherkin "Documentation on godoc for gherkin" | ||||
|  |  | |||
|  | @ -8,14 +8,18 @@ import ( | |||
| ) | ||||
| 
 | ||||
| // Arg is an argument for StepHandler parsed from | ||||
| // the regexp submatch to handle the step | ||||
| // the regexp submatch to handle the step. | ||||
| // | ||||
| // In future versions, it may be replaced with | ||||
| // an argument injection toolkit using reflect | ||||
| // package. | ||||
| type Arg struct { | ||||
| 	value interface{} | ||||
| } | ||||
| 
 | ||||
| // StepArgument func creates a step argument. | ||||
| // used in cases when calling another step from | ||||
| // within a StepHandlerFunc | ||||
| // within a StepHandler function. | ||||
| func StepArgument(value interface{}) *Arg { | ||||
| 	return &Arg{value: value} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										42
									
								
								builder.go
									
										
									
									
									
								
							
							
						
						
									
										42
									
								
								builder.go
									
										
									
									
									
								
							|  | @ -22,8 +22,8 @@ type builder struct { | |||
| 	tpl      *template.Template | ||||
| } | ||||
| 
 | ||||
| func newBuilder() *builder { | ||||
| 	return &builder{ | ||||
| func newBuilder(buildPath string) (*builder, error) { | ||||
| 	b := &builder{ | ||||
| 		files: make(map[string]*ast.File), | ||||
| 		fset:  token.NewFileSet(), | ||||
| 		tpl: template.Must(template.New("main").Parse(`package main | ||||
|  | @ -39,6 +39,18 @@ func main() { | |||
| 	suite.Run() | ||||
| }`)), | ||||
| 	} | ||||
| 
 | ||||
| 	return b, filepath.Walk(buildPath, func(path string, file os.FileInfo, err error) error { | ||||
| 		if file.IsDir() && file.Name() != "." { | ||||
| 			return filepath.SkipDir | ||||
| 		} | ||||
| 		if err == nil && strings.HasSuffix(path, ".go") { | ||||
| 			if err := b.parseFile(path); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return err | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (b *builder) parseFile(path string) error { | ||||
|  | @ -129,24 +141,18 @@ func (b *builder) merge() (*ast.File, error) { | |||
| 	return ast.MergePackageFiles(pkg, ast.FilterImportDuplicates), nil | ||||
| } | ||||
| 
 | ||||
| // Build creates a runnable godog executable file | ||||
| // from current package source and test files | ||||
| // it merges the files with the help of go/ast into | ||||
| // Build creates a runnable Godog executable file | ||||
| // from current package source and test source files. | ||||
| // | ||||
| // The package files are merged with the help of go/ast into | ||||
| // a single main package file which has a custom | ||||
| // main function to run features | ||||
| // main function to run test suite features. | ||||
| // | ||||
| // Currently, to manage imports we use "golang.org/x/tools/imports" | ||||
| // package, but that may be replaced in order to have | ||||
| // no external dependencies | ||||
| func Build() ([]byte, error) { | ||||
| 	b := newBuilder() | ||||
| 	err := filepath.Walk(".", func(path string, file os.FileInfo, err error) error { | ||||
| 		if file.IsDir() && file.Name() != "." { | ||||
| 			return filepath.SkipDir | ||||
| 		} | ||||
| 		if err == nil && strings.HasSuffix(path, ".go") { | ||||
| 			if err := b.parseFile(path); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return err | ||||
| 	}) | ||||
| 	b, err := newBuilder(".") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										7
									
								
								example/README.md
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										7
									
								
								example/README.md
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,7 @@ | |||
| # ls feature | ||||
| 
 | ||||
| In order to test our **ls** feature with **Godog**, run: | ||||
| 
 | ||||
|     go install github.com/DATA-DOG/godog/cmd/godog | ||||
|     $GOPATH/bin/godog ls.feature | ||||
| 
 | ||||
							
								
								
									
										27
									
								
								example/ls.feature
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										27
									
								
								example/ls.feature
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,27 @@ | |||
| Feature: ls | ||||
|   In order to see the directory structure | ||||
|   As a UNIX user | ||||
|   I need to be able to list directory contents | ||||
| 
 | ||||
|   Background: | ||||
|     Given I am in a directory "test" | ||||
| 
 | ||||
|   Scenario: lists files in directory | ||||
|     Given I have a file named "foo" | ||||
|     And I have a file named "bar" | ||||
|     When I run ls | ||||
|     Then I should get output: | ||||
|       """ | ||||
|       bar | ||||
|       foo | ||||
|       """ | ||||
| 
 | ||||
|   Scenario: lists files and directories | ||||
|     Given I have a file named "foo" | ||||
|     And I have a directory named "dir" | ||||
|     When I run ls | ||||
|     Then I should get output: | ||||
|       """ | ||||
|       dir | ||||
|       foo | ||||
|       """ | ||||
							
								
								
									
										34
									
								
								example/ls.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										34
									
								
								example/ls.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,34 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
| 	var location string | ||||
| 	switch { | ||||
| 	case os.Args[1] != "": | ||||
| 		location = os.Args[1] | ||||
| 	default: | ||||
| 		location = "." | ||||
| 	} | ||||
| 	if err := ls(location, os.Stdout); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ls(path string, w io.Writer) error { | ||||
| 	return filepath.Walk(path, func(p string, f os.FileInfo, err error) error { | ||||
| 		switch { | ||||
| 		case f.IsDir() && f.Name() != "." && f.Name() != ".." && filepath.Base(path) != f.Name(): | ||||
| 			w.Write([]byte(f.Name() + "\n")) | ||||
| 			return filepath.SkipDir | ||||
| 		case !f.IsDir(): | ||||
| 			w.Write([]byte(f.Name() + "\n")) | ||||
| 		} | ||||
| 		return err | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										65
									
								
								example/ls_test.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										65
									
								
								example/ls_test.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,65 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/DATA-DOG/godog" | ||||
| ) | ||||
| 
 | ||||
| type lsFeature struct { | ||||
| 	dir string | ||||
| 	buf *bytes.Buffer | ||||
| } | ||||
| 
 | ||||
| func lsFeatureContext(s godog.Suite) { | ||||
| 	c := &lsFeature{buf: bytes.NewBuffer(make([]byte, 1024))} | ||||
| 
 | ||||
| 	s.Step(`^I am in a directory "([^"]*)"$`, c.iAmInDirectory) | ||||
| 	s.Step(`^I have a (file|directory) named "([^"]*)"$`, c.iHaveFileOrDirectoryNamed) | ||||
| 	s.Step(`^I run ls$`, c.iRunLs) | ||||
| 	s.Step(`^I should get output:$`, c.iShouldGetOutput) | ||||
| } | ||||
| 
 | ||||
| func (f *lsFeature) iAmInDirectory(args ...*godog.Arg) error { | ||||
| 	f.dir = os.TempDir() + "/" + args[0].String() | ||||
| 	if err := os.RemoveAll(f.dir); err != nil && !os.IsNotExist(err) { | ||||
| 		return err | ||||
| 	} | ||||
| 	return os.Mkdir(f.dir, 0775) | ||||
| } | ||||
| 
 | ||||
| func (f *lsFeature) iHaveFileOrDirectoryNamed(args ...*godog.Arg) (err error) { | ||||
| 	if len(f.dir) == 0 { | ||||
| 		return fmt.Errorf("the directory was not chosen yet") | ||||
| 	} | ||||
| 	switch args[0].String() { | ||||
| 	case "file": | ||||
| 		err = ioutil.WriteFile(f.dir+"/"+args[1].String(), []byte{}, 0664) | ||||
| 	case "directory": | ||||
| 		err = os.Mkdir(f.dir+"/"+args[1].String(), 0775) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (f *lsFeature) iShouldGetOutput(args ...*godog.Arg) error { | ||||
| 	expected := args[0].PyString().Lines | ||||
| 	actual := strings.Split(strings.TrimSpace(f.buf.String()), "\n") | ||||
| 	if len(expected) != len(actual) { | ||||
| 		return fmt.Errorf("number of expected output lines %d, does not match actual: %d", len(expected), len(actual)) | ||||
| 	} | ||||
| 	for i, line := range actual { | ||||
| 		if line != expected[i] { | ||||
| 			return fmt.Errorf(`expected line "%s" at position: %d to match "%s", but it did not`, expected[i], i, line) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (f *lsFeature) iRunLs(args ...*godog.Arg) error { | ||||
| 	f.buf.Reset() | ||||
| 	return ls(f.dir, f.buf) | ||||
| } | ||||
							
								
								
									
										7
									
								
								fmt.go
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								fmt.go
									
										
									
									
									
								
							|  | @ -7,7 +7,12 @@ import ( | |||
| ) | ||||
| 
 | ||||
| // Formatter is an interface for feature runner | ||||
| // output summary presentation | ||||
| // output summary presentation. | ||||
| // | ||||
| // New formatters may be created to represent | ||||
| // suite results in different ways. These new | ||||
| // formatters needs to be registered with a | ||||
| // RegisterFormatter function call | ||||
| type Formatter interface { | ||||
| 	Node(interface{}) | ||||
| 	Failed(*gherkin.Step, *StepDef, error) | ||||
|  |  | |||
|  | @ -24,9 +24,7 @@ var outlinePlaceholderRegexp *regexp.Regexp = regexp.MustCompile("<[^>]+>") | |||
| type pretty struct { | ||||
| 	feature         *gherkin.Feature | ||||
| 	commentPos      int | ||||
| 	doneBackground bool | ||||
| 	background     *gherkin.Background | ||||
| 	scenario       *gherkin.Scenario | ||||
| 	backgroundSteps int | ||||
| 
 | ||||
| 	// outline | ||||
| 	outlineExamples int | ||||
|  | @ -56,21 +54,17 @@ func (f *pretty) Node(node interface{}) { | |||
| 			fmt.Println("") | ||||
| 		} | ||||
| 		f.feature = t | ||||
| 		f.scenario = nil | ||||
| 		f.background = nil | ||||
| 		f.features = append(f.features, t) | ||||
| 		// print feature header | ||||
| 		fmt.Println(bcl(t.Token.Keyword+": ", white) + t.Title) | ||||
| 		fmt.Println(t.Description) | ||||
| 	case *gherkin.Background: | ||||
| 		// do not repeat background for the same feature | ||||
| 		if f.background == nil && f.scenario == nil { | ||||
| 			f.background = t | ||||
| 			f.commentPos = longestStep(t.Steps, t.Token.Length()) | ||||
| 			// print background node | ||||
| 			fmt.Println("\n" + s(t.Token.Indent) + bcl(t.Token.Keyword+":", white)) | ||||
| 		// print background header | ||||
| 		if t.Background != nil { | ||||
| 			f.commentPos = longestStep(t.Background.Steps, t.Background.Token.Length()) | ||||
| 			f.backgroundSteps = len(t.Background.Steps) | ||||
| 			fmt.Println("\n" + s(t.Background.Token.Indent) + bcl(t.Background.Token.Keyword+":", white)) | ||||
| 		} | ||||
| 	case *gherkin.Scenario: | ||||
| 		f.scenario = t | ||||
| 		f.commentPos = longestStep(t.Steps, t.Token.Length()) | ||||
| 		if t.Outline != nil { | ||||
| 			f.outlineSteps = []interface{}{} // reset steps list | ||||
|  | @ -162,10 +156,10 @@ func (f *pretty) Summary() { | |||
| 	fmt.Println(elapsed) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) printOutlineExample() { | ||||
| func (f *pretty) printOutlineExample(scenario *gherkin.Scenario) { | ||||
| 	var failed error | ||||
| 	clr := green | ||||
| 	tbl := f.scenario.Outline.Examples | ||||
| 	tbl := scenario.Outline.Examples | ||||
| 	firstExample := f.outlineExamples == len(tbl.Rows)-1 | ||||
| 
 | ||||
| 	for i, act := range f.outlineSteps { | ||||
|  | @ -187,7 +181,7 @@ func (f *pretty) printOutlineExample() { | |||
| 		if firstExample { | ||||
| 			// in first example, we need to print steps | ||||
| 			var text string | ||||
| 			ostep := f.scenario.Outline.Steps[i] | ||||
| 			ostep := scenario.Outline.Steps[i] | ||||
| 			if def != nil { | ||||
| 				if m := outlinePlaceholderRegexp.FindAllStringIndex(ostep.Text, -1); len(m) > 0 { | ||||
| 					var pos int | ||||
|  | @ -216,7 +210,7 @@ func (f *pretty) printOutlineExample() { | |||
| 	max := longest(tbl) | ||||
| 	// an example table header | ||||
| 	if firstExample { | ||||
| 		out := f.scenario.Outline | ||||
| 		out := scenario.Outline | ||||
| 		fmt.Println("") | ||||
| 		fmt.Println(s(out.Token.Indent) + bcl(out.Token.Keyword+":", white)) | ||||
| 		row := tbl.Rows[0] | ||||
|  | @ -308,15 +302,18 @@ func (f *pretty) printStepKind(stepAction interface{}) { | |||
| 	step, def, c, err = f.stepDetails(stepAction) | ||||
| 
 | ||||
| 	// do not print background more than once | ||||
| 	if f.scenario == nil && step.Background != f.background { | ||||
| 	switch { | ||||
| 	case step.Background != nil && f.backgroundSteps == 0: | ||||
| 		return | ||||
| 	case step.Background != nil && f.backgroundSteps > 0: | ||||
| 		f.backgroundSteps -= 1 | ||||
| 	} | ||||
| 
 | ||||
| 	if f.outlineExamples != 0 { | ||||
| 		f.outlineSteps = append(f.outlineSteps, stepAction) | ||||
| 		if len(f.outlineSteps) == f.outlineNumSteps { | ||||
| 			// an outline example steps has went through | ||||
| 			f.printOutlineExample() | ||||
| 			f.printOutlineExample(step.Scenario) | ||||
| 			f.outlineExamples -= 1 | ||||
| 		} | ||||
| 		return // wait till example steps | ||||
|  | @ -385,7 +382,7 @@ func longestStep(steps []*gherkin.Step, base int) int { | |||
| 	ret := base | ||||
| 	for _, step := range steps { | ||||
| 		length := step.Token.Length() | ||||
| 		if length > base { | ||||
| 		if length > ret { | ||||
| 			ret = length | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										
											Двоичные данные
										
									
								
								gherkin/example/example
									
										
									
									
									
								
							
							
						
						
									
										
											Двоичные данные
										
									
								
								gherkin/example/example
									
										
									
									
									
								
							
										
											Двоичный файл не отображается.
										
									
								
							|  | @ -1,15 +0,0 @@ | |||
| Feature: ls | ||||
|   In order to see the directory structure | ||||
|   As a UNIX user | ||||
|   I need to be able to list the current directory's contents | ||||
| 
 | ||||
|   Scenario: | ||||
|     Given I am in a directory "test" | ||||
|     And I have a file named "foo" | ||||
|     And I have a file named "bar" | ||||
|     When I run "ls" | ||||
|     Then I should get: | ||||
|       """ | ||||
|       bar | ||||
|       foo | ||||
|       """ | ||||
|  | @ -1,21 +0,0 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"log" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/DATA-DOG/godog/gherkin" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
| 	feature, err := gherkin.ParseFile("ls.feature") | ||||
| 	switch { | ||||
| 	case err == gherkin.ErrEmpty: | ||||
| 		log.Println("the feature file is empty and does not describe any feature") | ||||
| 		return | ||||
| 	case err != nil: | ||||
| 		log.Println("the feature file is incorrect or could not be read:", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 	log.Println("have parsed a feature:", feature.Title, "with", len(feature.Scenarios), "scenarios") | ||||
| } | ||||
							
								
								
									
										66
									
								
								suite.go
									
										
									
									
									
								
							
							
						
						
									
										66
									
								
								suite.go
									
										
									
									
									
								
							|  | @ -16,26 +16,30 @@ import ( | |||
| // it can be either a string or a *regexp.Regexp | ||||
| type Regexp interface{} | ||||
| 
 | ||||
| // StepHandler is a function contract for | ||||
| // step handler | ||||
| // StepHandler is a func to handle the step | ||||
| // | ||||
| // It receives all arguments which | ||||
| // will be matched according to the regular expression | ||||
| // The handler receives all arguments which | ||||
| // will be matched according to the Regexp | ||||
| // which is passed with a step registration. | ||||
| // The error in return - represents a reason of failure. | ||||
| // | ||||
| // Returning signals that the step has finished | ||||
| // and that the feature runner can move on to the next | ||||
| // step. | ||||
| // The error in return - represents a reason of failure. | ||||
| // All consequent scenario steps are skipped. | ||||
| // | ||||
| // Returning signals that the step has finished and that | ||||
| // the feature runner can move on to the next step. | ||||
| type StepHandler func(...*Arg) error | ||||
| 
 | ||||
| // ErrUndefined is returned in case if step definition was not found | ||||
| var ErrUndefined = fmt.Errorf("step is undefined") | ||||
| 
 | ||||
| // StepDef is a registered step definition | ||||
| // contains a StepHandler, a regexp which | ||||
| // is used to match a step and Args which | ||||
| // were matched by last step | ||||
| // contains a StepHandler and regexp which | ||||
| // is used to match a step. Args which | ||||
| // were matched by last executed step | ||||
| // | ||||
| // This structure is passed to the formatter | ||||
| // when step is matched and is either failed | ||||
| // or successful | ||||
| type StepDef struct { | ||||
| 	Args    []*Arg | ||||
| 	Handler StepHandler | ||||
|  | @ -43,7 +47,16 @@ type StepDef struct { | |||
| } | ||||
| 
 | ||||
| // Suite is an interface which allows various contexts | ||||
| // to register step definitions and event handlers | ||||
| // to register steps and event handlers. | ||||
| // | ||||
| // When running a test suite, this interface is passed | ||||
| // to all functions (contexts), which have it as a | ||||
| // first and only argument. | ||||
| // | ||||
| // Note that all event hooks does not catch panic errors | ||||
| // in order to have a trace information. Only step | ||||
| // executions are catching panic error since it may | ||||
| // be a context specific error. | ||||
| type Suite interface { | ||||
| 	Step(expr Regexp, h StepHandler) | ||||
| 	// suite events | ||||
|  | @ -80,17 +93,16 @@ 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 expr | ||||
| // 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 | ||||
| // will be applied | ||||
| // will be applied. | ||||
| // | ||||
| // If none of the StepHandlers are matched, then a pending | ||||
| // step error will be raised. | ||||
| // If none of the StepHandlers are matched, then | ||||
| // ErrUndefined error will be returned. | ||||
| func (s *suite) Step(expr Regexp, h StepHandler) { | ||||
| 	var regex *regexp.Regexp | ||||
| 
 | ||||
|  | @ -112,13 +124,20 @@ func (s *suite) Step(expr Regexp, h StepHandler) { | |||
| } | ||||
| 
 | ||||
| // BeforeSuite registers a function or method | ||||
| // to be run once before suite runner | ||||
| // to be run once before suite runner. | ||||
| // | ||||
| // Use it to prepare the test suite for a spin. | ||||
| // Connect and prepare database for instance... | ||||
| func (s *suite) BeforeSuite(f func()) { | ||||
| 	s.beforeSuiteHandlers = append(s.beforeSuiteHandlers, f) | ||||
| } | ||||
| 
 | ||||
| // BeforeScenario registers a function or method | ||||
| // to be run before every scenario | ||||
| // to be run before every scenario. | ||||
| // | ||||
| // It is a good practice to restore the default state | ||||
| // before every scenario so it would be isolated from | ||||
| // any kind of state. | ||||
| func (s *suite) BeforeScenario(f func(*gherkin.Scenario)) { | ||||
| 	s.beforeScenarioHandlers = append(s.beforeScenarioHandlers, f) | ||||
| } | ||||
|  | @ -131,6 +150,13 @@ func (s *suite) BeforeStep(f func(*gherkin.Step)) { | |||
| 
 | ||||
| // AfterStep registers an function or method | ||||
| // to be run after every scenario | ||||
| // | ||||
| // It may be convenient to return a different kind of error | ||||
| // in order to print more state details which may help | ||||
| // in case of step failure | ||||
| // | ||||
| // In some cases, for example when running a headless | ||||
| // browser, to take a screenshot after failure. | ||||
| func (s *suite) AfterStep(f func(*gherkin.Step, error)) { | ||||
| 	s.afterStepHandlers = append(s.afterStepHandlers, f) | ||||
| } | ||||
|  | @ -147,7 +173,7 @@ func (s *suite) AfterSuite(f func()) { | |||
| 	s.afterSuiteHandlers = append(s.afterSuiteHandlers, f) | ||||
| } | ||||
| 
 | ||||
| // Run - runs a godog feature suite | ||||
| // Run starts the Godog feature suite | ||||
| func (s *suite) Run() { | ||||
| 	var err error | ||||
| 	if !flag.Parsed() { | ||||
|  |  | |||
							
								
								
									
										2
									
								
								utils.go
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								utils.go
									
										
									
									
									
								
							|  | @ -6,10 +6,12 @@ import ( | |||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // a color code type | ||||
| type color int | ||||
| 
 | ||||
| const ansiEscape = "\x1b" | ||||
| 
 | ||||
| // some ansi colors | ||||
| const ( | ||||
| 	black color = iota + 30 | ||||
| 	red | ||||
|  |  | |||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 gedi
						gedi