Cucumber, Selenium and Gherkin have become popular tools for helping teams implement test automation or what is often referred to as Acceptance Test Driver Development (ATDD) or Behavior Driven Development (BDD). In this article we will cover some more advanced features of the Gherkin language that can help you write tests that are simpler and more reusable.
We will cover:
- Using Regular Expressions for Dynamic Data
- Scenario Outlines
- Tables as Arguments
In this article series we use Ruby as the implementation language (and we recommend Ruby when there is no other existing preference). However, these examples will translate easily to other languages like Java.
1. Using Regular Expression for Dynamic Data
In our earlier blog, we showed you how to create Step Definitions in Ruby that translate plain text Gherkin steps into actions that will interact with the system. For example:
Would need a Step Definition inf Ruby that looks like this:
In this simple example, things work well, but what if you want to use a Given/When/Then statement but include dynamic data so you can reuse this statement in other tests? Let's take another example:
And the Step Definition:
If we want to create tests for different search values, we need to parameterize the value of the word "agile" so we can run tests for different terms. To do this we can use regular expressions to make this more dynamic. To do this we need to change our Ruby Step Definition:
We have replaced the hard coded value of "agile" with the regular expression of (.*) and added a parameter to the Ruby When function of |keyword|. This will set the variable keyword to any value that matches the regular expression. You can create more complex regular expressions and map those to multiple variables:
If you are not familiar with Regular Expressions (knows as RegEx), they are a special text string for describing a search pattern. Take a look at the site RegExr to learn more regular expressions. I have also found that Rubular is a nice site for testing your regular expressions in Ruby.
As you write more tests you will begin to find that you end up repeating the same steps over and over again. In Gherkin a "background" is a simple way to reduce the wordiness of Gherkin. Lets take this simple example:
If we create more scenarios we can see how this will quickly become unwieldy. As a result we can use the syntax "Background" to list steps that should be executed for every Scenario in a given Feature.
Notice how in the above example we were able to reduce the number of lines and simplify the Gherkin. But while using Background is better, there is still a great deal of repetition and this is where Scenario Outlines are helpful.
3. Scenario Outlines
Scenario Outlines allow you to design your Gherkin in such a way that you repeat the steps in the scenario once for each row in a set of inputs. In your Given, When or Then statements you can substitute the hard coded values for a variable placeholder like <keyword>. Then you add the "Examples" keyword and use the pipe/table format to specify the input data. The test will be run once for each row created in the table.
While Scenario Outlines are very useful I would caution against trying to use Automated Functional Tests as a way to test business logic. Business logic is best tested using Unit Tests or Integration Tests (i.e. API tests, etc). For Functional (or UI) tests the recommendation is to focus on testing the behavior of the UI and not on the business logic.
4. Tables as Arguments
In some cases, you will find you need a test to verify some list or set of data on a page. Rather than hard code this into your Step Definition you can use the Gherkin "Tables as Arguments" feature to pass a table of data to a Step Definition. Let's take this example - you have a web page which displays a list of cities (Philadelphia, New York, Cleveland, Orlando, etc). You could write your Gherkin this way:
Since this is quite repetitive we can use Tables as Arguments instead. The Gherkin would be:
And the Step Definition in Ruby would look like:
The table gets passed into the Step Definition as a hash of key/value pairs and we can loop through and verify each element which was passed in can be found on the page.
In our examples above, we created only automated functional tests but it's important to remember this is only one part of a good automation strategy, which will also include integration and unit tests.