diff --git a/docs/step-attributes.md b/docs/step-attributes.md index a8cc8be..0e58f65 100644 --- a/docs/step-attributes.md +++ b/docs/step-attributes.md @@ -4,7 +4,11 @@ You apply step attribute to a method which should handle the step execution as a Purpose of a step attribute is to provide text that matches the step text. Optionally it can extract values out of the step text and pass those values into the parameters of the method. -All this is done using [.NET Regex syntax](https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference), so make sure that you account for rules governing Regex language if you have complex matching use cases. +You can use either .NET regex syntax or cucumber expressions (recommended for simpler matching rules such as primitive types). The two sections below will go into more details. + +## Using .NET Regex Syntax + +Using [.NET Regex syntax](https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference), your attributes should specify a valid regex pattern that will match the step text and extract the values using regex groups. For example: ```C# @@ -12,7 +16,7 @@ For example: public void I_chose_first_number(int firstNumber) ``` -This code will match a step text if it looks like this: `Given I chose 12 as first number`. That's because in Regex, `(\d+)` will match any number of consecutive digits, such as `12`. +This code will match a step text if it looks like this: `Given I chose 12 as first number`. That's because in Regex, `(\d+)` will match any number of consecutive digits, such as `12`. Additionally, since it's a regex group (recognized by the enclosing parentheses), the matching value (in this case, 12), will end up in the method's argument (`int firstNumber`). Here are commonly seen use cases that need to be handled carefully, accounting Regex syntax rules: @@ -34,6 +38,26 @@ Here are commonly seen use cases that need to be handled carefully, accounting R | Given Coffee costs $5.00 today | Given(@"Coffee costs ([\d\\.]+) today") | any type | error: will not match dollar sign | | Given My Brothers' names are Kevin, Lucas, Paul | Given(@"My Brothers' names are ((?:\w+,\s*)+\w+)") | string | Kevin, Lucas, Paul| +## Cucumber Expressions + +If you only require simple patterns like integers, words or strings, you can use [cucumber expressions](https://github.com/cucumber/cucumber-expressions#readme), which is a simple alternative for the more complex regex expressions. With cucumber expressions, the above example can be rewritten to: +```C# +[Given(@"I chose {int} as first number")] +public void I_chose_first_number(int firstNumber) +``` + +Besides simplicity, cucumber expressions have the added benefit of being a formal specification other tools can look for. For instance by providing placeholders for code autocompletion in Visual Studio Code, as implemented by the plugin [VSCucumberAutoComplete](https://github.com/alexkrechik/VSCucumberAutoComplete). + +Xunit.Gherkin.Quick supports the following cucumber expressions: + +| Expression | Purpose | Corresponding regular expression | +| ---------- | ------- | -------------------------------- | +| {int} | Integer numbers | `[+-]?\d+` | +| {float} | Floating point numbers | `[+-]?([0-9]\*[.])?[0-9]+` | +| {word} | Single word without whitespace | `\w+` | +| {string} | Quoted strings | `("[^"]*")\|('[^']*')` | +| {} | Anything | `.*` | + ## Special characters within scenario steps Some texts will use BDD notation in the form: