Skip to content

Commit

Permalink
Merge pull request #364 from cucumber/allow_empty_return_step
Browse files Browse the repository at this point in the history
feat(step_definition): Allows to define step function without return.
  • Loading branch information
vearutop authored Jul 22, 2021
2 parents 48c0e0d + cdbb0ac commit 15358d2
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 45 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt

### Added

* Support for step definitions without return ([364](https://github.com/cucumber/godog/pull/364) -[titouanfreville])

### Changed

* Upgraded gherkin-go to v19 ([402](https://github.com/cucumber/godog/pull/402) - [mbow])
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ Feature: eat godogs

You may change **return godog.ErrPending** to **return nil** in the three step definitions and the scenario will pass successfully.

Also, you may omit error return if your step does not fail.

```go
func iEat(arg1 int) {
// Eat arg1.
}
```

#### Step 5 - Create the main program to test

We only need a number of **godogs** for now. Lets keep it simple.
Expand Down
1 change: 1 addition & 0 deletions features/tags.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Feature: tag filters
Background:
Given passing step
And passing step without return
Scenario Outline: parse a scenario
Given a feature path "<path>"
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/cucumber/messages-go/v16 v16.0.1
github.com/hashicorp/go-memdb v1.3.0
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/smartystreets/goconvey v1.6.4
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
Expand Down Expand Up @@ -109,6 +110,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
Expand Down Expand Up @@ -161,7 +163,9 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
Expand Down
48 changes: 31 additions & 17 deletions internal/models/stepdef.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package models

import (
"errors"
"fmt"
"reflect"
"strconv"
Expand All @@ -12,6 +13,13 @@ import (

var typeOfBytes = reflect.TypeOf([]byte(nil))

// matchable errors
var (
ErrUnmatchedStepArgumentNumber = errors.New("func received more arguments than expected")
ErrCannotConvert = errors.New("cannot convert argument")
ErrUnsupportedArgumentType = errors.New("unsupported argument type")
)

// StepDefinition ...
type StepDefinition struct {
formatters.StepDefinition
Expand All @@ -28,8 +36,9 @@ type StepDefinition struct {
func (sd *StepDefinition) Run() interface{} {
typ := sd.HandlerValue.Type()
if len(sd.Args) < typ.NumIn() {
return fmt.Errorf("func expects %d arguments, which is more than %d matched from step", typ.NumIn(), len(sd.Args))
return fmt.Errorf("%w: expected %d arguments, matched %d from step", ErrUnmatchedStepArgumentNumber, typ.NumIn(), len(sd.Args))
}

var values []reflect.Value
for i := 0; i < typ.NumIn(); i++ {
param := typ.In(i)
Expand All @@ -41,7 +50,7 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseInt(s, 10, 0)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to int: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to int: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(int(v)))
case reflect.Int64:
Expand All @@ -51,17 +60,17 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to int64: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to int64: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(int64(v)))
values = append(values, reflect.ValueOf(v))
case reflect.Int32:
s, err := sd.shouldBeString(i)
if err != nil {
return err
}
v, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to int32: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to int32: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(int32(v)))
case reflect.Int16:
Expand All @@ -71,7 +80,7 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseInt(s, 10, 16)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to int16: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to int16: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(int16(v)))
case reflect.Int8:
Expand All @@ -81,7 +90,7 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseInt(s, 10, 8)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to int8: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to int8: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(int8(v)))
case reflect.String:
Expand All @@ -97,7 +106,7 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseFloat(s, 64)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to float64: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to float64: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(v))
case reflect.Float32:
Expand All @@ -107,7 +116,7 @@ func (sd *StepDefinition) Run() interface{} {
}
v, err := strconv.ParseFloat(s, 32)
if err != nil {
return fmt.Errorf(`cannot convert argument %d: "%s" to float32: %s`, i, s, err)
return fmt.Errorf(`%w %d: "%s" to float32: %s`, ErrCannotConvert, i, s, err)
}
values = append(values, reflect.ValueOf(float32(v)))
case reflect.Ptr:
Expand All @@ -124,7 +133,7 @@ func (sd *StepDefinition) Run() interface{} {
break
}

return fmt.Errorf(`cannot convert argument %d: "%v" of type "%T" to *messages.PickleStepArgument_PickleDocString`, i, arg, arg)
return fmt.Errorf(`%w %d: "%v" of type "%T" to *messages.PickleDocString`, ErrCannotConvert, i, arg, arg)
case "messages.PickleTable":
if v, ok := arg.(*messages.PickleStepArgument); ok {
values = append(values, reflect.ValueOf(v.DataTable))
Expand All @@ -136,9 +145,9 @@ func (sd *StepDefinition) Run() interface{} {
break
}

return fmt.Errorf(`cannot convert argument %d: "%v" of type "%T" to *messages.PickleStepArgument_PickleTable`, i, arg, arg)
return fmt.Errorf(`%w %d: "%v" of type "%T" to *messages.PickleStepArgument_PickleTable`, ErrCannotConvert, i, arg, arg)
default:
return fmt.Errorf("the argument %d type %T is not supported %s", i, arg, param.Elem().String())
return fmt.Errorf("%w: the argument %d type %T is not supported %s", ErrUnsupportedArgumentType, i, arg, param.Elem().String())
}
case reflect.Slice:
switch param {
Expand All @@ -149,14 +158,19 @@ func (sd *StepDefinition) Run() interface{} {
}
values = append(values, reflect.ValueOf([]byte(s)))
default:
return fmt.Errorf("the slice argument %d type %s is not supported", i, param.Kind())
return fmt.Errorf("%w: the slice argument %d type %s is not supported", ErrUnsupportedArgumentType, i, param.Kind())
}
default:
return fmt.Errorf("the argument %d type %s is not supported", i, param.Kind())
return fmt.Errorf("%w: the argument %d type %s is not supported", ErrUnsupportedArgumentType, i, param.Kind())
}
}

return sd.HandlerValue.Call(values)[0].Interface()
res := sd.HandlerValue.Call(values)
if len(res) == 0 {
return nil
}

return res[0].Interface()
}

func (sd *StepDefinition) shouldBeString(idx int) (string, error) {
Expand All @@ -166,13 +180,13 @@ func (sd *StepDefinition) shouldBeString(idx int) (string, error) {
return arg, nil
case *messages.PickleStepArgument:
if arg.DocString == nil {
return "", fmt.Errorf(`cannot convert DocString is not set`)
return "", fmt.Errorf(`%w %d: "%v" of type "%T": DocString is not set`, ErrCannotConvert, idx, arg, arg)
}
return arg.DocString.Content, nil
case *messages.PickleDocString:
return arg.Content, nil
default:
return "", fmt.Errorf(`cannot convert argument %d: "%v" of type "%T" to string`, idx, arg, arg)
return "", fmt.Errorf(`%w %d: "%v" of type "%T" to string`, ErrCannotConvert, idx, arg, arg)
}
}

Expand Down
Loading

0 comments on commit 15358d2

Please sign in to comment.