Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/given when then snippet #596

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
test:
strategy:
matrix:
go-version: [ 1.16.x, 1.17.x, 1.19.x, 1.20.x, 1.21.x ] # Lowest supported and current stable versions.
go-version: [ 1.17.x, 1.19.x, 1.20.x, 1.21.x ] # Lowest supported and current stable versions.
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt

## Unreleased

### Added

- Option SnippetFunc to select a snippet func for generating code for missing steps ([596](https://github.com/cucumber/godog/pull/596) - [crosscode-nl](https://github.com/crosscode-nl))
- Added SnippetFunc "gwt_func" to generate Given/When/Then step snippets ([596](https://github.com/cucumber/godog/pull/596) - [crosscode-nl](https://github.com/crosscode-nl))
- Added SnippetFunc "step_func" to generate Step snippets - this is the original and the default functionality ([596](https://github.com/cucumber/godog/pull/596) - [crosscode-nl](https://github.com/crosscode-nl))
- Added command line argument "snippet-func" that allows providing the snippet func via command line ([596](https://github.com/cucumber/godog/pull/596) - [crosscode-nl](https://github.com/crosscode-nl))

### Changed

- BREAKING CHANGE, changed formatters.FormatterFunc to take a snippetFunc string parameter ([596](https://github.com/cucumber/godog/pull/596) - [crosscode-nl](https://github.com/crosscode-nl))

### Deprecated

- Dropped support for Go v1.16. The strings.Title function is deprecated and the package to use is golang.org/x/text/cases, but that package is not compatible with Go v.1.16.x

## [v0.13.0]
### Added
- Support for reading feature files from an `fs.FS` ([550](https://github.com/cucumber/godog/pull/550) - [tigh-latte](https://github.com/tigh-latte))
Expand Down
8 changes: 4 additions & 4 deletions _examples/custom-formatter/emoji.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ func init() {
godog.Format("emoji", "Progress formatter with emojis", emojiFormatterFunc)
}

func emojiFormatterFunc(suite string, out io.Writer) godog.Formatter {
return newEmojiFmt(suite, out)
func emojiFormatterFunc(suite string, out io.Writer, snippetFunc string) godog.Formatter {
return newEmojiFmt(suite, out, snippetFunc)
}

func newEmojiFmt(suite string, out io.Writer) *emojiFmt {
func newEmojiFmt(suite string, out io.Writer, snippetFunc string) *emojiFmt {
return &emojiFmt{
ProgressFmt: godog.NewProgressFmt(suite, out),
ProgressFmt: godog.NewProgressFmt(suite, out, snippetFunc),
out: out,
}
}
Expand Down
32 changes: 32 additions & 0 deletions _examples/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
213 changes: 213 additions & 0 deletions _examples/snippets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Snippets

Snippets are generated when undefined steps are created.

Currently, we support the following snippet functions:

| name | description |
|------------|-------------------------------------------------------------------|
| step_func | Generates steps with the Step keyword and function bodies |
| gwt_func | Generates steps with Given/When/Then keywords and function bodies |

Examples show the difference between each snippet generator.

## Examples

The first example uses the *step_func* snippet function to generate the snippet. This works by not providing a
snippet func or explicitly providing *step_func*. This example does not provide the snippet function explicitly.

Run the following command to view the output of the step_func example.

```shell
go test -test.v ./step_func
```

The output should be:

```
=== RUN TestFeatures
Feature: eat godogs
In order to be happy
As a hungry gopher
I need to be able to eat godogs
=== RUN TestFeatures/Eat_12_out_of_12
=== RUN TestFeatures/Eat_5_out_of_12

Scenario: Eat 12 out of 12 # features/godogs.feature:11
Given there are 12 godogs

Scenario: Eat 5 out of 12 # features/godogs.feature:6
Given there are 12 godogs
When I eat 12
Then there should be none remaining
When I eat 5
Then there should be 7 remaining

2 scenarios (2 undefined)
6 steps (6 undefined)
271.125µs

You can implement step definitions for undefined steps with these snippets:

func iEat(arg1 int) error {
return godog.ErrPending
}

func thereAreGodogs(arg1 int) error {
return godog.ErrPending
}

func thereShouldBeNoneRemaining() error {
return godog.ErrPending
}

func thereShouldBeRemaining(arg1 int) error {
return godog.ErrPending
}

func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.When(`^I eat (\d+)$`, iEat)
ctx.Given(`^there are (\d+) godogs$`, thereAreGodogs)
ctx.Then(`^there should be none remaining$`, thereShouldBeNoneRemaining)
ctx.Then(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

--- PASS: TestFeatures (0.00s)
--- PASS: TestFeatures/Eat_12_out_of_12 (0.00s)
--- PASS: TestFeatures/Eat_5_out_of_12 (0.00s)
PASS
ok github.com/cucumber/godog/_examples/snippets/gwt_func (cached)
```

The second example uses the *gwt_func* snippet function to generate the snippet. This works by providing a
snippet func or explicitly.

```go
var opts = godog.Options{
Output: colors.Colored(os.Stdout),
SnippetFunc: "gwt_func",
Concurrency: 4,
}
```

Run the following command to view the output of the gwt_func example.

```shell
go test -test.v ./gwt_func
```

The output should be:

```
=== RUN TestFeatures
Feature: eat godogs
In order to be happy
As a hungry gopher
I need to be able to eat godogs
=== RUN TestFeatures/Eat_12_out_of_12
=== RUN TestFeatures/Eat_5_out_of_12

Scenario: Eat 12 out of 12 # features/godogs.feature:11
Given there are 12 godogs

Scenario: Eat 5 out of 12 # features/godogs.feature:6
Given there are 12 godogs
When I eat 12
Then there should be none remaining
When I eat 5
Then there should be 7 remaining

2 scenarios (2 undefined)
6 steps (6 undefined)
271.125µs

You can implement step definitions for undefined steps with these snippets:

func iEat(arg1 int) error {
return godog.ErrPending
}

func thereAreGodogs(arg1 int) error {
return godog.ErrPending
}

func thereShouldBeNoneRemaining() error {
return godog.ErrPending
}

func thereShouldBeRemaining(arg1 int) error {
return godog.ErrPending
}

func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.When(`^I eat (\d+)$`, iEat)
ctx.Given(`^there are (\d+) godogs$`, thereAreGodogs)
ctx.Then(`^there should be none remaining$`, thereShouldBeNoneRemaining)
ctx.Then(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

--- PASS: TestFeatures (0.00s)
```

The third option demonstrates selecting a snippet function using command line arguments.

```shell
go test ./step_func -test.v -godog.snippet-func gwt_func
```

The output should be:

```
=== RUN TestFeatures
Feature: eat godogs
In order to be happy
As a hungry gopher
I need to be able to eat godogs
=== RUN TestFeatures/Eat_12_out_of_12

Scenario: Eat 12 out of 12 # features/godogs.feature:11
Given there are 12 godogs
=== RUN TestFeatures/Eat_5_out_of_12

Scenario: Eat 5 out of 12 # features/godogs.feature:6
Given there are 12 godogs
When I eat 12
Then there should be none remaining
When I eat 5
Then there should be 7 remaining

2 scenarios (2 undefined)
6 steps (6 undefined)
427.166µs

You can implement step definitions for undefined steps with these snippets:

func iEat(arg1 int) error {
return godog.ErrPending
}

func thereAreGodogs(arg1 int) error {
return godog.ErrPending
}

func thereShouldBeNoneRemaining() error {
return godog.ErrPending
}

func thereShouldBeRemaining(arg1 int) error {
return godog.ErrPending
}

func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.When(`^I eat (\d+)$`, iEat)
ctx.Given(`^there are (\d+) godogs$`, thereAreGodogs)
ctx.Then(`^there should be none remaining$`, thereShouldBeNoneRemaining)
ctx.Then(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

--- PASS: TestFeatures (0.00s)
--- PASS: TestFeatures/Eat_12_out_of_12 (0.00s)
--- PASS: TestFeatures/Eat_5_out_of_12 (0.00s)
PASS
ok github.com/cucumber/godog/_examples/snippets/step_func 0.222s
```
14 changes: 14 additions & 0 deletions _examples/snippets/gwt_func/features/godogs.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
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

Scenario: Eat 12 out of 12
Given there are 12 godogs
When I eat 12
Then there should be none remaining
37 changes: 37 additions & 0 deletions _examples/snippets/gwt_func/godogs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gwt_func

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)
}
Loading
Loading