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.
If you are not familiar with Selenium, Cucumber and Gherkin take a look at our related introductory blog "The 5 Step Guide for Selenium, Cucumber, and Gherkin".
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 Rubulr 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. For more on this, see our related blog about organizational testing strategy.
To become an ICAgile Certified Professional in Agile Testing or to learn more about automation and Agile testing check out our courses.
Learn more about modernized technology here:
Interested in training to help advance your agile journey? Click the button to view our current list of public training courses! Use code BLOG10 for 10% off!