feat(step_definition): Allows to define step function without return.

Issue: It is not possible to use function without return when
       matching steps, resulting in a lot of Nil only error
       returns.

Fix: Allows to provide empty result function by correctly matching
     reflect Calls on step Handler.
     When nothing is returned by the Handler, it will return
     nil as if errors was nil.
Этот коммит содержится в:
tfreville 2020-12-10 12:35:47 +01:00 коммит произвёл Viacheslav Poturaev
родитель 9a335aed22
коммит fbed999ad8
6 изменённых файлов: 47 добавлений и 18 удалений

Просмотреть файл

@ -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>"

Просмотреть файл

@ -156,7 +156,11 @@ func (sd *StepDefinition) Run() interface{} {
}
}
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) {

Просмотреть файл

@ -12,6 +12,27 @@ import (
"github.com/cucumber/godog/internal/models"
)
func TestShouldSupportEmptyHandlerReturn(t *testing.T) {
fn := func(a int64, b int32, c int16, d int8) {}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "1", "1", "1"}
if err := def.Run(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
def.Args = []interface{}{"1", "1", "1", strings.Repeat("1", 9)}
if err := def.Run(); err == nil {
t.Fatalf("expected convertion fail for int8, but got none")
}
}
func TestShouldSupportIntTypes(t *testing.T) {
fn := func(a int64, b int32, c int16, d int8) error { return nil }

Просмотреть файл

@ -569,6 +569,7 @@ type progressOutput struct {
}
func passingStepDef() error { return nil }
func passingStepDefWithoutReturn() {}
func oddEvenStepDef(odd, even int) error { return oddOrEven(odd, even) }

Просмотреть файл

@ -108,6 +108,7 @@ func InitializeScenario(ctx *ScenarioContext) {
return nil
})
ctx.Step(`^(?:a )?passing step without return$`, func() {})
ctx.BeforeStep(tc.inject)
}
@ -424,9 +425,8 @@ func (tc *godogFeaturesScenario) aFeatureFile(path string, body *DocString) erro
return err
}
func (tc *godogFeaturesScenario) featurePath(path string) error {
func (tc *godogFeaturesScenario) featurePath(path string) {
tc.paths = append(tc.paths, path)
return nil
}
func (tc *godogFeaturesScenario) parseFeatures() error {

Просмотреть файл

@ -176,8 +176,8 @@ func (ctx *ScenarioContext) Step(expr, stepFunc interface{}) {
panic(fmt.Sprintf("expected handler to be func, but got: %T", stepFunc))
}
if typ.NumOut() != 1 {
panic(fmt.Sprintf("expected handler to return only one value, but it has: %d", typ.NumOut()))
if typ.NumOut() > 1 {
panic(fmt.Sprintf("expected handler to return either zero or one value, but it has: %d", typ.NumOut()))
}
def := &models.StepDefinition{
@ -188,6 +188,7 @@ func (ctx *ScenarioContext) Step(expr, stepFunc interface{}) {
HandlerValue: v,
}
if typ.NumOut() == 1 {
typ = typ.Out(0)
switch typ.Kind() {
case reflect.Interface:
@ -202,6 +203,7 @@ func (ctx *ScenarioContext) Step(expr, stepFunc interface{}) {
default:
panic(fmt.Sprintf("expected handler to return an error or []string, but got: %s", typ.Kind()))
}
}
ctx.suite.steps = append(ctx.suite.steps, def)
}