diff --git a/_examples/godogs/godogs.go b/_examples/godogs/godogs.go index f8604e26..50569feb 100644 --- a/_examples/godogs/godogs.go +++ b/_examples/godogs/godogs.go @@ -1,4 +1,37 @@ package godogs -// Godogs available to eat. -var Godogs int +import ( + "fmt" +) + +// Godogs is an example behavior holder. +type Godogs int + +// Add increments Godogs count. +func (g *Godogs) Add(n int) { + *g = *g + Godogs(n) +} + +// Eat decrements Godogs count or fails if there is not enough available. +func (g *Godogs) Eat(n int) error { + ng := Godogs(n) + + if (g == nil && ng > 0) || ng > *g { + return fmt.Errorf("you cannot eat %d godogs, there are %d available", n, g.Available()) + } + + if ng > 0 { + *g = *g - ng + } + + return nil +} + +// Available returns the number of currently available Godogs. +func (g *Godogs) Available() int { + if g == nil { + return 0 + } + + return int(*g) +} diff --git a/_examples/godogs/godogs_test.go b/_examples/godogs/godogs_test.go index ec0965f3..58482d8c 100644 --- a/_examples/godogs/godogs_test.go +++ b/_examples/godogs/godogs_test.go @@ -1,4 +1,4 @@ -package godogs +package godogs_test // This example shows how to set up test suite runner with Go subtests and godog command line parameters. // Sample commands: @@ -15,6 +15,7 @@ import ( "context" "flag" "fmt" + "github.com/cucumber/godog/_examples/godogs" "os" "testing" @@ -22,7 +23,10 @@ import ( "github.com/cucumber/godog/colors" ) -var opts = godog.Options{Output: colors.Colored(os.Stdout)} +var opts = godog.Options{ + Output: colors.Colored(os.Stdout), + Concurrency: 4, +} func init() { godog.BindFlags("godog.", flag.CommandLine, &opts) @@ -48,38 +52,54 @@ func TestFeatures(t *testing.T) { } } -func thereAreGodogs(available int) error { - Godogs = available - return nil +type godogsCtxKey struct{} + +func godogsToContext(ctx context.Context, g godogs.Godogs) context.Context { + return context.WithValue(ctx, godogsCtxKey{}, &g) } -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 godogsFromContext(ctx context.Context) *godogs.Godogs { + g, _ := ctx.Value(godogsCtxKey{}).(*godogs.Godogs) + + return g +} + +// Concurrent execution of scenarios may lead to race conditions on shared resources. +// Use context to maintain data separation and avoid data races. + +// Step definition can optionally receive context as a first argument. + +func thereAreGodogs(ctx context.Context, available int) { + godogsFromContext(ctx).Add(available) } -func thereShouldBeRemaining(remaining int) error { - if Godogs != remaining { - return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs) +// Step definition can return error, context, context and error, or nothing. + +func iEat(ctx context.Context, num int) error { + return godogsFromContext(ctx).Eat(num) +} + +func thereShouldBeRemaining(ctx context.Context, remaining int) error { + available := godogsFromContext(ctx).Available() + if available != remaining { + return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, available) } + return nil } -func thereShouldBeNoneRemaining() error { - return thereShouldBeRemaining(0) +func thereShouldBeNoneRemaining(ctx context.Context) error { + return thereShouldBeRemaining(ctx, 0) } func InitializeTestSuite(ctx *godog.TestSuiteContext) { - ctx.BeforeSuite(func() { Godogs = 0 }) + ctx.BeforeSuite(func() { fmt.Println("Get the party started!") }) } func InitializeScenario(ctx *godog.ScenarioContext) { ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) { - Godogs = 0 // clean the state before every scenario - return ctx, nil + // Add initial godogs to context. + return godogsToContext(ctx, 0), nil }) ctx.Step(`^there are (\d+) godogs$`, thereAreGodogs) diff --git a/_examples/incorrect-project-structure/go.sum b/_examples/incorrect-project-structure/go.sum index 6e2ac94b..d8a82844 100644 --- a/_examples/incorrect-project-structure/go.sum +++ b/_examples/incorrect-project-structure/go.sum @@ -1,13 +1,17 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cucumber/gherkin/go/v26 v26.0.2 h1:DjNKtTIv5VG0F1XaJ2xYNk+ck8pJWRNFzyajkc/Y4l4= github.com/cucumber/gherkin/go/v26 v26.0.2/go.mod h1:Xf+SrSuFbivEDZvmHjTShord3zlEkqsj7QB4sxl1SuU= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= +github.com/cucumber/messages/go/v22 v22.0.0/go.mod h1:aZipXTKc0JnjCsXrJnuZpWhtay93k7Rn3Dee7iyPJjs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -15,6 +19,7 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-memdb v1.3.2 h1:RBKHOsnSszpU6vxq80LzC2BaQjuuvoyaQbkLTf7V7g8= github.com/hashicorp/go-memdb v1.3.2/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -22,6 +27,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -37,6 +43,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -46,6 +53,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=