Repository: go-bdd/gobdd (go)

Issue:
Formalize AddStep
**Is your feature request related to a problem? Please describe.**
Currently the first parameter of `AddStep` allows passing various types:

- `string`
- `[]byte`
- `*regexp.Regex`

I think the API here could be improved a bit. It's easier to code when functions have definitive types.

**Describe the solution you'd like**
I think the most common usage is `suite.AddStep(`some string step definition`)`, so I would make the first parameter `string`.

I don't really see why would anyone use a byte slice here. Are there any use cases for that? Maybe we could remove this one.

Finally I would add a `suite.AddRegexStep` function for accepting a regex instance.


**Additional context**
I understand this is just polishing, and in a testing use case using reflection doesn't matter that much, but having an easy to read and understand API makes using the library easier.

WDYT?

Pull request description:
Improve AddStep
Took a stab at an easier one: #53

Closes #53

I wasn't sure where to put the tests for this change.

Patch:
diff --git a/gobdd.go b/gobdd.go
index 3cfe762..b9950b0 100644
--- a/gobdd.go
+++ b/gobdd.go
@@ -99,38 +99,53 @@ func NewSuite(t *testing.T, options SuiteOptions) *Suite {
 	}
 }
 
-// Adds a step to the suite
-// The first parameter is the step definition which can be:
+// AddStep registers a step in the suite.
 //
-// * string which will be converted to a regexp
-// * [] byte which will be converted to a regexp as well
-// * regexp
+// The second parameter is the step function that gets executed
+// when a step definition matches the provided regular expression.
 //
-// No other types are supported
+// A step function can have any number of parameters (even zero),
+// but it MUST accept a context.Context as the first parameter (if there is any)
+// and MUST return a context and an error:
 //
-// The second parameter is a function which will be executed when while running a scenario one of the steps will match
-// the given pattern
-func (s *Suite) AddStep(step interface{}, f interface{}) error {
-	err := validateStepFunc(f)
+// 	func myStepFunction(ctx context.Context, first int, second int) (context.Context, error) {
+// 		return ctx, nil
+// 	}
+func (s *Suite) AddStep(expr string, step interface{}) error {
+	err := validateStepFunc(step)
 	if err != nil {
 		return err
 	}
-	var regex *regexp.Regexp
-
-	switch t := step.(type) {
-	case *regexp.Regexp:
-		regex = t
-	case string:
-		regex = regexp.MustCompile(t)
-	case []byte:
-		regex = regexp.MustCompile(string(t))
-	default:
-		return fmt.Errorf("expecting expr to be a *regexp.Regexp or a string, got type: %T", step)
+
+	s.steps = append(s.steps, stepDef{
+		expr: regexp.MustCompile(expr),
+		f:    step,
+	})
+
+	return nil
+}
+
+// AddRegexStep registers a step in the suite.
+//
+// The second parameter is the step function that gets executed
+// when a step definition matches the provided regular expression.
+//
+// A step function can have any number of parameters (even zero),
+// but it MUST accept a context.Context as the first parameter (if there is any)
+// and MUST return a context and an error:
+//
+// 	func myStepFunction(ctx context.Context, first int, second int) (context.Context, error) {
+// 		return ctx, nil
+// 	}
+func (s *Suite) AddRegexStep(expr *regexp.Regexp, step interface{}) error {
+	err := validateStepFunc(step)
+	if err != nil {
+		return err
 	}
 
 	s.steps = append(s.steps, stepDef{
-		expr: regex,
-		f:    f,
+		expr: expr,
+		f:    step,
 	})
 
 	return nil


Test patch:
diff --git a/testhttp/setup.go b/testhttp/setup.go
index 508989b..d4284c3 100644
--- a/testhttp/setup.go
+++ b/testhttp/setup.go
@@ -12,7 +12,7 @@ import (
 )
 
 type addStepper interface {
-	AddStep(step interface{}, f interface{}) error
+	AddStep(definition string, step interface{}) error
 }
 
 type testHTTPMethods struct {