instead of Suite interface expose Suite struct
* 570d70a update examples regarding Suite interface removal, closes #11
Этот коммит содержится в:
родитель
46f5218d36
коммит
ca36316b7a
19 изменённых файлов: 142 добавлений и 234 удалений
38
README.md
38
README.md
|
@ -25,11 +25,15 @@ not changed most likely. I'll try to respect **backward compatibility** as much
|
|||
|
||||
### Example
|
||||
|
||||
The following example can be [found here](https://github.com/DATA-DOG/godog/tree/master/examples/godogs).
|
||||
|
||||
#### Step 1
|
||||
|
||||
Imagine we have a **godog cart** to serve godogs for dinner. At first, we describe our feature
|
||||
in plain text:
|
||||
|
||||
``` gherkin
|
||||
# file: /tmp/godog/godog.feature
|
||||
# file: examples/godogs/godog.feature
|
||||
Feature: eat godogs
|
||||
In order to be happy
|
||||
As a hungry gopher
|
||||
|
@ -44,22 +48,27 @@ Feature: eat godogs
|
|||
As a developer, your work is done as soon as you’ve made the program behave as
|
||||
described in the Scenario.
|
||||
|
||||
If you run `godog godog.feature` inside the **/tmp/godog** directory.
|
||||
#### Step 2
|
||||
|
||||
If you run `godog godog.feature` inside the **examples/godogs** directory.
|
||||
You should see that the steps are undefined:
|
||||
|
||||

|
||||
|
||||
It gives you undefined step snippets to implement in your test context. You may copy these snippets
|
||||
into **godog_test.go** file.
|
||||
into your `*_test.go` file.
|
||||
|
||||
Now if you run the tests again. You should see that the definition is now pending. You may change
|
||||
**ErrPending** to **nil** and the scenario will pass successfully.
|
||||
|
||||
Since we need a working implementation, we may start by implementing what is necessary.
|
||||
We only need a number of **godogs** for now.
|
||||
Since we need a working implementation, we may start by implementing only what is necessary.
|
||||
|
||||
#### Step 3
|
||||
|
||||
We only need a number of **godogs** for now. Lets define steps.
|
||||
|
||||
``` go
|
||||
/* file: /tmp/godog/godog.go */
|
||||
/* file: examples/godogs/godog.go */
|
||||
package main
|
||||
|
||||
var Godogs int
|
||||
|
@ -67,10 +76,12 @@ var Godogs int
|
|||
func main() { /* usual main func */ }
|
||||
```
|
||||
|
||||
#### Step 4
|
||||
|
||||
Now lets finish our step implementations in order to test our feature requirements:
|
||||
|
||||
``` go
|
||||
/* file: /tmp/godog/godog_test.go */
|
||||
/* file: examples/godogs/godog_test.go */
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -99,7 +110,7 @@ func thereShouldBeRemaining(remaining int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func featureContext(s godog.Suite) {
|
||||
func featureContext(s *godog.Suite) {
|
||||
s.Step(`^there are (\d+) godogs$`, thereAreGodogs)
|
||||
s.Step(`^I eat (\d+)$`, iEat)
|
||||
s.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
|
||||
|
@ -126,8 +137,15 @@ See `godog -h` for general command options.
|
|||
|
||||
See implementation examples:
|
||||
|
||||
- [rest API server](https://github.com/DATA-DOG/godog/tree/master/examples/api) implementation and tests
|
||||
- [ls command](https://github.com/DATA-DOG/godog/tree/master/examples/ls) implementation and tests
|
||||
- [rest API server](https://github.com/DATA-DOG/godog/tree/master/examples/api)
|
||||
- [godogs](https://github.com/DATA-DOG/godog/tree/master/examples/godogs)
|
||||
|
||||
### Changes
|
||||
|
||||
**2015-07-03**
|
||||
- changed **godog.Suite** from interface to struct. Context registration should be updated accordingly. The reason
|
||||
for change: since it exports the same methods and there is no need to mock a function in tests, there is no
|
||||
obvious reason to keep an interface.
|
||||
|
||||
### FAQ
|
||||
|
||||
|
|
15
builder.go
15
builder.go
|
@ -82,7 +82,7 @@ func (b *builder) parseFile(path string) error {
|
|||
b.Internal = true
|
||||
}
|
||||
b.deleteMainFunc(f)
|
||||
b.registerSteps(f)
|
||||
b.registerContexts(f)
|
||||
b.deleteImports(f)
|
||||
b.files[path] = f
|
||||
|
||||
|
@ -122,27 +122,30 @@ func (b *builder) deleteMainFunc(f *ast.File) {
|
|||
f.Decls = decls
|
||||
}
|
||||
|
||||
func (b *builder) registerSteps(f *ast.File) {
|
||||
func (b *builder) registerContexts(f *ast.File) {
|
||||
for _, d := range f.Decls {
|
||||
switch fun := d.(type) {
|
||||
case *ast.FuncDecl:
|
||||
for _, param := range fun.Type.Params.List {
|
||||
switch expr := param.Type.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
case *ast.StarExpr:
|
||||
switch x := expr.X.(type) {
|
||||
case *ast.Ident:
|
||||
if x.Name == "godog" && expr.Sel.Name == "Suite" {
|
||||
if x.Name == "Suite" {
|
||||
b.Contexts = append(b.Contexts, fun.Name.Name)
|
||||
}
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
switch t := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
if expr.Name == "Suite" {
|
||||
if t.Name == "godog" && x.Sel.Name == "Suite" {
|
||||
b.Contexts = append(b.Contexts, fun.Name.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *builder) merge() (*ast.File, error) {
|
||||
|
|
|
@ -75,7 +75,7 @@ func (a *apiFeature) theResponseShouldMatchJSON(body *gherkin.DocString) error {
|
|||
return godog.ErrPending
|
||||
}
|
||||
|
||||
func featureContext(s godog.Suite) {
|
||||
func featureContext(s *godog.Suite) {
|
||||
api := &apiFeature{}
|
||||
s.Step(`^I send "([^"]*)" request to "([^"]*)"$`, api.iSendrequestTo)
|
||||
s.Step(`^the response code should be (\d+)$`, api.theResponseCodeShouldBe)
|
||||
|
@ -158,7 +158,7 @@ func (a *apiFeature) theResponseShouldMatchJSON(body *gherkin.DocString) (err er
|
|||
return
|
||||
}
|
||||
|
||||
func featureContext(s godog.Suite) {
|
||||
func featureContext(s *godog.Suite) {
|
||||
api := &apiFeature{}
|
||||
|
||||
s.BeforeScenario(api.resetResponse)
|
||||
|
|
|
@ -67,7 +67,7 @@ func (a *apiFeature) theResponseShouldMatchJSON(body *gherkin.DocString) (err er
|
|||
return
|
||||
}
|
||||
|
||||
func featureContext(s godog.Suite) {
|
||||
func featureContext(s *godog.Suite) {
|
||||
api := &apiFeature{}
|
||||
|
||||
s.BeforeScenario(api.resetResponse)
|
||||
|
|
Двоичные данные
examples/api/screenshots/undefined.png
Двоичные данные
examples/api/screenshots/undefined.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 151 КиБ После Ширина: | Высота: | Размер: 148 КиБ |
|
@ -117,7 +117,7 @@ func (a *apiFeature) thereAreUsers(users *gherkin.DataTable) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func featureContext(s godog.Suite) {
|
||||
func featureContext(s *godog.Suite) {
|
||||
api := &apiFeature{}
|
||||
|
||||
s.BeforeScenario(api.resetResponse)
|
||||
|
|
9
examples/godogs/godog.feature
Обычный файл
9
examples/godogs/godog.feature
Обычный файл
|
@ -0,0 +1,9 @@
|
|||
Feature: eat godogs
|
||||
In order to be happy
|
||||
As a hungry gopher
|
||||
I need to be able to eat godogs
|
||||
|
||||
Scenario: Eat 5 out of 12
|
||||
Given there are 12 godogs
|
||||
When I eat 5
|
||||
Then there should be 7 remaining
|
5
examples/godogs/godog.go
Обычный файл
5
examples/godogs/godog.go
Обычный файл
|
@ -0,0 +1,5 @@
|
|||
package main
|
||||
|
||||
var Godogs int
|
||||
|
||||
func main() { /* usual main func */ }
|
37
examples/godogs/godog_test.go
Обычный файл
37
examples/godogs/godog_test.go
Обычный файл
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
)
|
||||
|
||||
func thereAreGodogs(available int) error {
|
||||
Godogs = available
|
||||
return nil
|
||||
}
|
||||
|
||||
func iEat(num int) error {
|
||||
if Godogs < num {
|
||||
return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
|
||||
}
|
||||
Godogs -= num
|
||||
return nil
|
||||
}
|
||||
|
||||
func thereShouldBeRemaining(remaining int) error {
|
||||
if Godogs != remaining {
|
||||
return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func featureContext(s *godog.Suite) {
|
||||
s.Step(`^there are (\d+) godogs$`, thereAreGodogs)
|
||||
s.Step(`^I eat (\d+)$`, iEat)
|
||||
s.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
|
||||
|
||||
s.BeforeScenario(func(interface{}) {
|
||||
Godogs = 0 // clean the state before every scenario
|
||||
})
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
# ls feature
|
||||
|
||||
In order to test our **ls** feature with **Godog**, run:
|
||||
|
||||
go get github.com/DATA-DOG/godog/cmd/godog
|
||||
$GOPATH/bin/godog ls.feature
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
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
|
||||
"""
|
|
@ -1,35 +0,0 @@
|
|||
// Example - demonstrates ls command implementation tests.
|
||||
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
|
||||
})
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/cucumber/gherkin-go"
|
||||
)
|
||||
|
||||
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(name string) error {
|
||||
f.dir = os.TempDir() + "/" + name
|
||||
if err := os.RemoveAll(f.dir); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return os.Mkdir(f.dir, 0775)
|
||||
}
|
||||
|
||||
func (f *lsFeature) iHaveFileOrDirectoryNamed(typ, name string) (err error) {
|
||||
if len(f.dir) == 0 {
|
||||
return fmt.Errorf("the directory was not chosen yet")
|
||||
}
|
||||
switch typ {
|
||||
case "file":
|
||||
err = ioutil.WriteFile(f.dir+"/"+name, []byte{}, 0664)
|
||||
case "directory":
|
||||
err = os.Mkdir(f.dir+"/"+name, 0775)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *lsFeature) iShouldGetOutput(names *gherkin.DocString) error {
|
||||
expected := strings.Split(names.Content, "\n")
|
||||
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() error {
|
||||
f.buf.Reset()
|
||||
return ls(f.dir, f.buf)
|
||||
}
|
4
flags.go
4
flags.go
|
@ -5,7 +5,9 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
func flags(s *suite) *flag.FlagSet {
|
||||
// Flags builds a *flag.FlagSet with all flags
|
||||
// required for the godog suite
|
||||
func flags(s *Suite) *flag.FlagSet {
|
||||
set := flag.NewFlagSet("godog", flag.ExitOnError)
|
||||
set.StringVar(&s.format, "format", "pretty", "")
|
||||
set.StringVar(&s.format, "f", "pretty", "")
|
||||
|
|
2
fmt.go
2
fmt.go
|
@ -30,7 +30,7 @@ var undefinedSnippetsTpl = template.Must(template.New("snippets").Funcs(snippetH
|
|||
return godog.ErrPending
|
||||
}
|
||||
|
||||
{{end}}func featureContext(s godog.Suite) { {{ range . }}
|
||||
{{end}}func featureContext(s *godog.Suite) { {{ range . }}
|
||||
s.Step({{ backticked .Expr }}, {{ .Method }}){{end}}
|
||||
}
|
||||
`))
|
||||
|
|
Двоичные данные
screenshots/undefined.png
Двоичные данные
screenshots/undefined.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 96 КиБ После Ширина: | Высота: | Размер: 109 КиБ |
109
suite.go
109
suite.go
|
@ -28,52 +28,18 @@ var ErrUndefined = fmt.Errorf("step is undefined")
|
|||
// step implementation is pending
|
||||
var ErrPending = fmt.Errorf("step implementation is pending")
|
||||
|
||||
// Suite is an interface which allows various contexts
|
||||
// Suite allows various contexts
|
||||
// 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.
|
||||
// When running a test suite, the instance of Suite
|
||||
// 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 {
|
||||
// Run the test suite
|
||||
Run()
|
||||
|
||||
// Registers a step which will execute stepFunc
|
||||
// on step expr match
|
||||
//
|
||||
// expr can be either a string or a *regexp.Regexp
|
||||
// stepFunc is a func to handle the step, arguments
|
||||
// are set from matched step
|
||||
Step(expr interface{}, h interface{})
|
||||
|
||||
// BeforeSuite registers a func to run on initial
|
||||
// suite startup
|
||||
BeforeSuite(f func())
|
||||
|
||||
// BeforeScenario registers a func to run before
|
||||
// every *gherkin.Scenario or *gherkin.ScenarioOutline
|
||||
BeforeScenario(f func(interface{}))
|
||||
|
||||
// BeforeStep register a handler before every step
|
||||
BeforeStep(f func(*gherkin.Step))
|
||||
|
||||
// AfterStep register a handler after every step
|
||||
AfterStep(f func(*gherkin.Step, error))
|
||||
|
||||
// AfterScenario registers a func to run after
|
||||
// every *gherkin.Scenario or *gherkin.ScenarioOutline
|
||||
AfterScenario(f func(interface{}, error))
|
||||
|
||||
// AfterSuite runs func int the end of tests
|
||||
AfterSuite(f func())
|
||||
}
|
||||
|
||||
type suite struct {
|
||||
type Suite struct {
|
||||
steps []*StepDef
|
||||
features []*feature
|
||||
fmt Formatter
|
||||
|
@ -98,24 +64,27 @@ type suite struct {
|
|||
}
|
||||
|
||||
// New initializes a Suite. The instance is passed around
|
||||
// to all context initialization functions from *_test.go files
|
||||
func New() Suite {
|
||||
return &suite{}
|
||||
// to all context initialization functions from *_test.go files.
|
||||
func New() *Suite {
|
||||
return &Suite{}
|
||||
}
|
||||
|
||||
// Step allows to register a StepHandler in Godog
|
||||
// feature suite, the handler will be applied to all
|
||||
// steps matching the given Regexp expr
|
||||
// Step allows to register a *StepDef in Godog
|
||||
// feature suite, the definition will be applied
|
||||
// to all steps matching the given Regexp expr.
|
||||
//
|
||||
// It will panic if expr is not a valid regular expression
|
||||
// It will panic if expr is not a valid regular
|
||||
// expression or stepFunc is not a valid step
|
||||
// handler.
|
||||
//
|
||||
// Note that if there are two handlers which may match
|
||||
// the same step, then the only first matched handler
|
||||
// Note that if there are two definitions which may match
|
||||
// the same step, then only the first matched handler
|
||||
// will be applied.
|
||||
//
|
||||
// If none of the StepHandlers are matched, then
|
||||
// ErrUndefined error will be returned.
|
||||
func (s *suite) Step(expr interface{}, stepFunc interface{}) {
|
||||
// If none of the *StepDef is matched, then
|
||||
// ErrUndefined error will be returned when
|
||||
// running steps.
|
||||
func (s *Suite) Step(expr interface{}, stepFunc interface{}) {
|
||||
var regex *regexp.Regexp
|
||||
|
||||
switch t := expr.(type) {
|
||||
|
@ -152,7 +121,7 @@ func (s *suite) Step(expr interface{}, stepFunc interface{}) {
|
|||
//
|
||||
// Use it to prepare the test suite for a spin.
|
||||
// Connect and prepare database for instance...
|
||||
func (s *suite) BeforeSuite(f func()) {
|
||||
func (s *Suite) BeforeSuite(f func()) {
|
||||
s.beforeSuiteHandlers = append(s.beforeSuiteHandlers, f)
|
||||
}
|
||||
|
||||
|
@ -165,13 +134,13 @@ func (s *suite) BeforeSuite(f func()) {
|
|||
// 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(interface{})) {
|
||||
func (s *Suite) BeforeScenario(f func(interface{})) {
|
||||
s.beforeScenarioHandlers = append(s.beforeScenarioHandlers, f)
|
||||
}
|
||||
|
||||
// BeforeStep registers a function or method
|
||||
// to be run before every scenario
|
||||
func (s *suite) BeforeStep(f func(*gherkin.Step)) {
|
||||
func (s *Suite) BeforeStep(f func(*gherkin.Step)) {
|
||||
s.beforeStepHandlers = append(s.beforeStepHandlers, f)
|
||||
}
|
||||
|
||||
|
@ -184,7 +153,7 @@ func (s *suite) BeforeStep(f func(*gherkin.Step)) {
|
|||
//
|
||||
// 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)) {
|
||||
func (s *Suite) AfterStep(f func(*gherkin.Step, error)) {
|
||||
s.afterStepHandlers = append(s.afterStepHandlers, f)
|
||||
}
|
||||
|
||||
|
@ -193,18 +162,18 @@ func (s *suite) AfterStep(f func(*gherkin.Step, error)) {
|
|||
//
|
||||
// The interface argument may be *gherkin.Scenario
|
||||
// or *gherkin.ScenarioOutline
|
||||
func (s *suite) AfterScenario(f func(interface{}, error)) {
|
||||
func (s *Suite) AfterScenario(f func(interface{}, error)) {
|
||||
s.afterScenarioHandlers = append(s.afterScenarioHandlers, f)
|
||||
}
|
||||
|
||||
// AfterSuite registers a function or method
|
||||
// to be run once after suite runner
|
||||
func (s *suite) AfterSuite(f func()) {
|
||||
func (s *Suite) AfterSuite(f func()) {
|
||||
s.afterSuiteHandlers = append(s.afterSuiteHandlers, f)
|
||||
}
|
||||
|
||||
// Run starts the Godog feature suite
|
||||
func (s *suite) Run() {
|
||||
func (s *Suite) Run() {
|
||||
flagSet := flags(s)
|
||||
fatal(flagSet.Parse(os.Args[1:]))
|
||||
|
||||
|
@ -249,7 +218,7 @@ func (s *suite) Run() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *suite) run() {
|
||||
func (s *Suite) run() {
|
||||
// run before suite handlers
|
||||
for _, f := range s.beforeSuiteHandlers {
|
||||
f()
|
||||
|
@ -269,7 +238,7 @@ func (s *suite) run() {
|
|||
s.fmt.Summary()
|
||||
}
|
||||
|
||||
func (s *suite) matchStep(step *gherkin.Step) *StepDef {
|
||||
func (s *Suite) matchStep(step *gherkin.Step) *StepDef {
|
||||
for _, h := range s.steps {
|
||||
if m := h.Expr.FindStringSubmatch(step.Text); len(m) > 0 {
|
||||
var args []interface{}
|
||||
|
@ -286,7 +255,7 @@ func (s *suite) matchStep(step *gherkin.Step) *StepDef {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
||||
func (s *Suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
||||
match := s.matchStep(step)
|
||||
if match == nil {
|
||||
s.fmt.Undefined(step)
|
||||
|
@ -330,7 +299,7 @@ func (s *suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *suite) runSteps(steps []*gherkin.Step, prevErr error) (err error) {
|
||||
func (s *Suite) runSteps(steps []*gherkin.Step, prevErr error) (err error) {
|
||||
err = prevErr
|
||||
for _, step := range steps {
|
||||
stepErr := s.runStep(step, err)
|
||||
|
@ -347,13 +316,13 @@ func (s *suite) runSteps(steps []*gherkin.Step, prevErr error) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *suite) skipSteps(steps []*gherkin.Step) {
|
||||
func (s *Suite) skipSteps(steps []*gherkin.Step) {
|
||||
for _, step := range steps {
|
||||
s.fmt.Skipped(step)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *suite) runOutline(outline *gherkin.ScenarioOutline, b *gherkin.Background) (failErr error) {
|
||||
func (s *Suite) runOutline(outline *gherkin.ScenarioOutline, b *gherkin.Background) (failErr error) {
|
||||
s.fmt.Node(outline)
|
||||
|
||||
for _, example := range outline.Examples {
|
||||
|
@ -403,7 +372,7 @@ func (s *suite) runOutline(outline *gherkin.ScenarioOutline, b *gherkin.Backgrou
|
|||
return
|
||||
}
|
||||
|
||||
func (s *suite) runFeature(f *feature) {
|
||||
func (s *Suite) runFeature(f *feature) {
|
||||
s.fmt.Feature(f.Feature, f.Path)
|
||||
for _, scenario := range f.ScenarioDefinitions {
|
||||
var err error
|
||||
|
@ -425,7 +394,7 @@ func (s *suite) runFeature(f *feature) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *suite) runScenario(scenario *gherkin.Scenario, b *gherkin.Background) (err error) {
|
||||
func (s *Suite) runScenario(scenario *gherkin.Scenario, b *gherkin.Background) (err error) {
|
||||
// run before scenario handlers
|
||||
for _, f := range s.beforeScenarioHandlers {
|
||||
f(scenario)
|
||||
|
@ -448,7 +417,7 @@ func (s *suite) runScenario(scenario *gherkin.Scenario, b *gherkin.Background) (
|
|||
return
|
||||
}
|
||||
|
||||
func (s *suite) printStepDefinitions() {
|
||||
func (s *Suite) printStepDefinitions() {
|
||||
var longest int
|
||||
for _, def := range s.steps {
|
||||
if longest < len(def.Expr.String()) {
|
||||
|
@ -465,7 +434,7 @@ func (s *suite) printStepDefinitions() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *suite) parseFeatures() (err error) {
|
||||
func (s *Suite) parseFeatures() (err error) {
|
||||
for _, pat := range s.paths {
|
||||
// check if line number is specified
|
||||
parts := strings.Split(pat, ":")
|
||||
|
@ -525,7 +494,7 @@ func (s *suite) parseFeatures() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *suite) applyTagFilter(ft *gherkin.Feature) {
|
||||
func (s *Suite) applyTagFilter(ft *gherkin.Feature) {
|
||||
if len(s.tags) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -585,7 +554,7 @@ func hasTag(tags []string, tag string) bool {
|
|||
}
|
||||
|
||||
// based on http://behat.readthedocs.org/en/v2.5/guides/6.cli.html#gherkin-filters
|
||||
func (s *suite) matchesTags(tags []string) (ok bool) {
|
||||
func (s *Suite) matchesTags(tags []string) (ok bool) {
|
||||
ok = true
|
||||
for _, andTags := range strings.Split(s.tags, "&&") {
|
||||
var okComma bool
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/cucumber/gherkin-go"
|
||||
)
|
||||
|
||||
func SuiteContext(s Suite) {
|
||||
func SuiteContext(s *Suite) {
|
||||
c := &suiteContext{}
|
||||
|
||||
s.BeforeScenario(c.ResetBeforeEachScenario)
|
||||
|
@ -50,7 +50,7 @@ type firedEvent struct {
|
|||
}
|
||||
|
||||
type suiteContext struct {
|
||||
testedSuite *suite
|
||||
testedSuite *Suite
|
||||
events []*firedEvent
|
||||
fmt *testFormatter
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ type suiteContext struct {
|
|||
func (s *suiteContext) ResetBeforeEachScenario(interface{}) {
|
||||
// reset whole suite with the state
|
||||
s.fmt = &testFormatter{}
|
||||
s.testedSuite = &suite{fmt: s.fmt}
|
||||
s.testedSuite = &Suite{fmt: s.fmt}
|
||||
// our tested suite will have the same context registered
|
||||
SuiteContext(s.testedSuite)
|
||||
// reset all fired events
|
||||
|
|
|
@ -5,14 +5,14 @@ import (
|
|||
)
|
||||
|
||||
func assertNotMatchesTagFilter(tags []string, filter string, t *testing.T) {
|
||||
s := &suite{tags: filter}
|
||||
s := &Suite{tags: filter}
|
||||
if s.matchesTags(tags) {
|
||||
t.Errorf(`expected tags: %v not to match tag filter "%s", but it did`, tags, filter)
|
||||
}
|
||||
}
|
||||
|
||||
func assertMatchesTagFilter(tags []string, filter string, t *testing.T) {
|
||||
s := &suite{tags: filter}
|
||||
s := &Suite{tags: filter}
|
||||
if !s.matchesTags(tags) {
|
||||
t.Errorf(`expected tags: %v to match tag filter "%s", but it did not`, tags, filter)
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче