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
- Backgrounds
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:
Given We navigate to the homepage
Would need a Step Definition inf Ruby that looks like this:
Given(/^We navigate to the homepage$/) do
$driver.navigate.to "http://mock.agiletrailblazers.com"
end
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:
When We search for the word agile
And the Step Definition:
When(/^We search for the word agile$/) do
driver.find_element(:id, 's').send_keys("agile")
driver.find_element(:id, 's').send_keys("\n")
end
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:
When(/^We search for the word (.*)$/) do |keyword|
$driver.find_element(:id, 's').send_keys(keyword)
$driver.find_element(:id, 's').send_keys("\n")
end
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:
When(/^the user enters a date of (\d+)\/(\d+)\/(\d+)$/) \
do |month,day,year|
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.
2. Backgrounds
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:
Feature: Site Search
Scenario:
Given We navigate to the homepage
When We search for the word agile
Then The result title Search Results for: agile will be displayed
And There are 12 results found
Scenario:
Given We navigate to the homepage
When We search for the word scrum
Then The result title Search Results for: scrum will be displayed
And There are 21 results found
Scenario:
Given We navigate to the homepage
When We search for the word kanban
Then The result title Search Results for: kanban will be displayed
And There are 6 results found
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.
Feature: Site Search
Background:
Given We navigate to the homepage
Scenario:
When We search for the word agile
Then The result title Search Results for: agile will be displayed
And There are 12 results found
Scenario:
When We search for the word scrum
Then The result title Search Results for: scrum will be displayed
And There are 21 results found
Scenario:
When We search for the word kanban
Then The result title Search Results for: kanban will be displayed
And There are 6 results found
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.
Feature: Site Search
Scenario Outline:
Given We navigate to the homepage
When We search for the word <keyword>
Then The result title <title> will be displayed
And There are <count> results found
Examples:
| keyword | title | count |
| agile | Search Results for: agile | 12 |
| scrum | Search Results for: scrum | 21 |
| kanban | Search Results for: kanban | 6 |
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:
Scenario: Validate the list of cities webpage
Given the user is on the cities webpage
Then confirm we see the the city Philadelphia
And confirm we see the the city New York
And confirm we see the the city Orlando
And confirm we see the the city Cleveland
And confirm we see the the city Pheonix
And confirm we see the the city Seattle
And confirm we see the the city Boston
Since this is quite repetitive we can use Tables as Arguments instead. The Gherkin would be:
Scenario: Validate the list of cities webpage
Given the user is on the cities webpage
Then confirm we see the following cities
| city |
| Philadelphia |
| New York |
| Orlando |
| Cleveland |
| Pheonix |
| Seattle |
| Boston |
And the Step Definition in Ruby would look like:
Then(/^confirm we see the following cities$/) do |table|
$wait = Selenium::WebDriver::Wait.new(:timeout => 5) # seconds
data = table.hashes
data.each do |row|
row.each do |key, value|
#locate each value from the table on the page
element = $wait.until { \
$driver.find_element(:xpath, './/*[contains(., "' + value + '")]') }
end
end
end
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.