diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 09389a8..23a5cec 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -7,5 +7,7 @@ main: url: /creating-steps.html - title: "Suite's options" url: /suite-options.html + - title: "Parameter types" + url: /parameter-types.html - title: "GitHub" url: https://github.com/go-bdd/gobdd diff --git a/docs/parameter-types.md b/docs/parameter-types.md new file mode 100644 index 0000000..073b98c --- /dev/null +++ b/docs/parameter-types.md @@ -0,0 +1,27 @@ +--- +layout: default +title: Parameter types +--- + +# Parameter types + +GoBDD has support for [parameter types](https://cucumber.io/docs/cucumber/cucumber-expressions/). There are a few predefined parameter types: + + * `{int}` - integer (-1 or 56) + * `{float}` - float (0.4 or 234.4) + * `{word}` - single word (`hello` or `pizza`) + * `{text}` - single-quoted or double-quoted strings (`'I like pizza'` or `"I like pizza"`) + +You can add your own parameter types using `AddParameterTypes()` function. Here are a few examples + +```go + s := gobdd.NewSuite(t) + s.AddParameterTypes(`{int}`, []string{`(\d)`}) + s.AddParameterTypes(`{float}`, []string{`([-+]?\d*\.?\d*)`}) + s.AddParameterTypes(`{word}`, []string{`([\d\w]+)`}) + s.AddParameterTypes(`{text}`, []string{`"([\d\w\-\s]+)"`, `'([\d\w\-\s]+)'`}) +``` + +The first argument accepts the parameter types. As the second parameter provides list of regular expressions that should replace the parameter. + +Parameter types should be added Before adding any step. \ No newline at end of file diff --git a/features/parameter-types.feature b/features/parameter-types.feature new file mode 100644 index 0000000..56539e6 --- /dev/null +++ b/features/parameter-types.feature @@ -0,0 +1,13 @@ +Feature: parameter types + Scenario: add two digits + When I add 1 and 2 + Then the result should equal 3 + Scenario: simple word + When I use word pizza + Scenario: simple text with double quotes + When I use text "I like pizza" + Scenario: simple text with single quotes + When I use text 'I like pizza' + Scenario: add two floats + When I add floats 1 and 2 + Then the result should equal float 3 \ No newline at end of file diff --git a/gobdd.go b/gobdd.go index 36551bf..42da0e0 100644 --- a/gobdd.go +++ b/gobdd.go @@ -20,10 +20,11 @@ import ( // Holds all the information about the suite (options, steps to execute etc) type Suite struct { - t TestingT - steps []stepDef - options SuiteOptions - hasStepErrors bool + t TestingT + steps []stepDef + options SuiteOptions + hasStepErrors bool + parameterTypes map[string][]string } // Holds all the information about how the suite or features/steps should be configured @@ -123,10 +124,37 @@ func NewSuite(t TestingT, optionClosures ...func(*SuiteOptions)) *Suite { optionClosures[i](&options) } - return &Suite{ - t: t, - steps: []stepDef{}, - options: options, + s := &Suite{ + t: t, + steps: []stepDef{}, + options: options, + parameterTypes: map[string][]string{}, + } + + s.AddParameterTypes(`{int}`, []string{`(\d)`}) + s.AddParameterTypes(`{float}`, []string{`([-+]?\d*\.?\d*)`}) + s.AddParameterTypes(`{word}`, []string{`([\d\w]+)`}) + s.AddParameterTypes(`{text}`, []string{`"([\d\w\-\s]+)"`, `'([\d\w\-\s]+)'`}) + + return s +} + +// AddParameterTypes adds a list of parameter types that will be used to simplify step definitions. +// +// The first argument is the parameter type and the second parameter is a list of regular expressions +// that should replace the parameter type. +// +// s.AddParameterTypes(`{int}`, []string{`(\d)`}) +// +// The regular expression should compile, otherwise will produce an error and stop executing. +func (s *Suite) AddParameterTypes(from string, to []string) { + for _, to := range to { + _, err := regexp.Compile(to) + if err != nil { + s.t.Fatalf(`the regular expresion for key %s doesn't compile: %s`, from, to) + } + + s.parameterTypes[from] = append(s.parameterTypes[from], to) } } @@ -149,18 +177,36 @@ func (s *Suite) AddStep(expr string, step interface{}) { return } - compiled, err := regexp.Compile(expr) - if err != nil { - s.t.Errorf("the step function is incorrect: %w", err) - s.hasStepErrors = true + exprs := s.applyParameterTypes(expr) - return + for _, expr := range exprs { + compiled, err := regexp.Compile(expr) + if err != nil { + s.t.Errorf("the step function is incorrect: %w", err) + s.hasStepErrors = true + + return + } + + s.steps = append(s.steps, stepDef{ + expr: compiled, + f: step, + }) } +} - s.steps = append(s.steps, stepDef{ - expr: compiled, - f: step, - }) +func (s *Suite) applyParameterTypes(expr string) []string { + exprs := []string{expr} + + for from, to := range s.parameterTypes { + for _, t := range to { + if strings.Contains(expr, from) { + exprs = append(exprs, strings.Replace(expr, from, t, -1)) + } + } + } + + return exprs } // AddRegexStep registers a step in the suite. diff --git a/gobdd_test.go b/gobdd_test.go index 9913f7f..d1c9155 100644 --- a/gobdd_test.go +++ b/gobdd_test.go @@ -43,6 +43,25 @@ func TestScenarioOutline(t *testing.T) { suite.Run() } +func TestParameterTypes(t *testing.T) { + suite := NewSuite(t, WithFeaturesPath("features/parameter-types.feature")) + suite.AddStep(`I add {int} and {int}`, add) + suite.AddStep(`the result should equal {int}`, check) + suite.AddStep(`I add floats {float} and {float}`, addf) + suite.AddStep(`the result should equal float {float}`, checkf) + suite.AddStep(`I use word {word}`, func(t StepTest, ctx Context, word string) { + if word != "pizza" { + t.Fatal("it should be pizza") + } + }) + suite.AddStep(`I use text {text}`, func(t StepTest, ctx Context, text string) { + if text != "I like pizza" { + t.Fatal("it should say that I like pizza") + } + }) + + suite.Run() +} func TestScenarioOutlineExecutesAllTests(t *testing.T) { c := 0