implements multistep - initial attempt

Этот коммит содержится в:
gedi 2017-04-26 20:33:13 +03:00
родитель 88d441e5ce
коммит ba80ebcd33
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 56604CDCCC201556
2 изменённых файлов: 60 добавлений и 11 удалений

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

@ -53,7 +53,7 @@ func (sd *StepDef) definitionID() string {
// run a step with the matched arguments using // run a step with the matched arguments using
// reflect // reflect
func (sd *StepDef) run() error { func (sd *StepDef) run() interface{} {
typ := sd.hv.Type() typ := sd.hv.Type()
if len(sd.args) < typ.NumIn() { 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("func expects %d arguments, which is more than %d matched from step", typ.NumIn(), len(sd.args))
@ -171,12 +171,7 @@ func (sd *StepDef) run() error {
return fmt.Errorf("the argument %d type %s is not supported", i, param.Kind()) return fmt.Errorf("the argument %d type %s is not supported", i, param.Kind())
} }
} }
ret := sd.hv.Call(values)[0].Interface() return sd.hv.Call(values)[0].Interface()
if nil == ret {
return nil
}
return ret.(error)
} }
func (sd *StepDef) shouldBeString(idx int) (string, error) { func (sd *StepDef) shouldBeString(idx int) (string, error) {

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

@ -95,12 +95,25 @@ func (s *Suite) Step(expr interface{}, stepFunc interface{}) {
if typ.Kind() != reflect.Func { if typ.Kind() != reflect.Func {
panic(fmt.Sprintf("expected handler to be func, but got: %T", stepFunc)) panic(fmt.Sprintf("expected handler to be func, but got: %T", stepFunc))
} }
if typ.NumOut() != 1 { if typ.NumOut() != 1 {
panic(fmt.Sprintf("expected handler to return an error, but it has more values in return: %d", typ.NumOut())) panic(fmt.Sprintf("expected handler to return only one value, but it has: %d", typ.NumOut()))
} }
if typ.Out(0).Kind() != reflect.Interface || !typ.Out(0).Implements(errorInterface) {
panic(fmt.Sprintf("expected handler to return an error interface, but we have: %s", typ.Out(0).Kind())) typ = typ.Out(0)
switch typ.Kind() {
case reflect.Interface:
if !typ.Implements(errorInterface) {
panic(fmt.Sprintf("expected handler to return an error, but got: %s", typ.Kind()))
}
case reflect.Slice:
if typ.Elem().Kind() != reflect.String {
panic(fmt.Sprintf("expected handler to return []string for multistep, but got: []%s", typ.Kind()))
}
default:
panic(fmt.Sprintf("expected handler to return an error or []string, but got: %s", typ.Kind()))
} }
s.steps = append(s.steps, &StepDef{ s.steps = append(s.steps, &StepDef{
Handler: stepFunc, Handler: stepFunc,
Expr: regex, Expr: regex,
@ -241,10 +254,51 @@ func (s *Suite) runStep(step *gherkin.Step, prevStepErr error) (err error) {
} }
}() }()
err = match.run() err = s.maybeSubSteps(match.run())
return return
} }
func (s *Suite) maybeSubSteps(result interface{}) error {
if nil == result {
return nil
}
if err, ok := result.(error); ok {
return err
}
steps, ok := result.([]string)
if !ok {
return fmt.Errorf("unexpected error, should have been []string: %T - %+v", result, result)
}
for _, step := range steps {
var def *StepDef
for _, h := range s.steps {
if m := h.Expr.FindStringSubmatch(step); len(m) > 0 {
var args []interface{}
for _, m := range m[1:] {
args = append(args, m)
}
h.args = args
def = h
break
}
}
if def == nil {
return ErrUndefined
}
// @TODO: step hooks only take gherkin.Step
// @TODO: cannot call formatter to register step execution either
if err := s.maybeSubSteps(def.run()); err != nil {
return err
}
}
return nil
}
func (s *Suite) runSteps(steps []*gherkin.Step, prevErr error) (err error) { func (s *Suite) runSteps(steps []*gherkin.Step, prevErr error) (err error) {
err = prevErr err = prevErr
for _, step := range steps { for _, step := range steps {