Defining the behaviour of your web site and testing that it works
Archive - Originally posted on "The Horse's Mouth" - 2015-05-30 11:56:24 - Graham EllisThis example uses ... Capybara, Cumumber, Gherkin, RSpec, Selenium and Ruby ... yes, you'll need an explanation later on of what all of these are!
Have you ever updates something on a website, only to find that it the process you've broken something else?
I've been teaching Behaviour Driven Development of web sites in Ruby this week - well not strictly "Behaviour driven nor developemnt" because the objective of my customer is to describe the required behaviour of an existing website in a codified way, and then be able to check that it behaves as it's suppose to. Not only behaving as it's supposed to today, but also into the future as the web site is enhanced.
How does this work?
1. I define my behaviour using the Gherkin language - here's a definition of some behaviours I would like to see from the website I'm working on:
Feature: Checking some things on quotations
Scenario: Looking for an onsite quote
Given I ask for a quotation for CA5 1RJ postcode
When I visit our quotation web page
Then I am told it is valid for Whitehaven
Given I ask for a quotation for IV14 5RD postcode
When I visit our quotation web page
Then I am told it is valid for Aberdeen
2. I run that through cucumber and it tells me where my tests are missing
WomanWithCat:cc grahamellis$ cucumber website
Feature: Checking some things on quotations
Scenario: Looking for an onsite quote # website/hello_quotation.feature:5
Given I ask for a quotation for CA5 1RJ postcode # website/hello_quotation.feature:6
When I visit our quotation web page # website/hello_quotation.feature:7
Then I am told it is valid for Whitehaven # website/hello_quotation.feature:8
Given I ask for a quotation for IV14 5RD postcode # website/hello_quotation.feature:14
When I visit our quotation web page # website/hello_quotation.feature:15
Then I am told it is valid for Aberdeen # website/hello_quotation.feature:16
1 scenario (1 undefined)
6 steps (6 undefined)
0m0.004s
You can implement step definitions for undefined steps with these snippets:
Given(/^I ask for a quotation for CA(\d+) (\d+)RJ postcode$/) do |arg1, arg2|
pending # express the regexp above with the code you wish you had
end
When(/^I visit our quotation web page$/) do
pending # express the regexp above with the code you wish you had
end
Then(/^I am told it is valid for Whitehaven$/) do
pending # express the regexp above with the code you wish you had
end
Given(/^I ask for a quotation for IV(\d+) (\d+)RD postcode$/) do |arg1, arg2|
pending # express the regexp above with the code you wish you had
end
Then(/^I am told it is valid for Aberdeen$/) do
pending # express the regexp above with the code you wish you had
end
If you want snippets in a different programming language,
just make sure a file with the appropriate file extension
exists where cucumber looks for step definitions.
WomanWithCat:cc grahamellis$
3. I copy and paste the suggested code template into a step definition file, and complete the tests:
require 'selenium-webdriver'
require 'capybara/cucumber'
require 'rspec/expectations'
Capybara.default_driver = :selenium
Given(/^I ask for a quotation for (.*) postcode$/) do |arg1|
@postcode = arg1
visit("http://www.wellho.net")
end
When(/^I visit our quotation web page$/) do
fill_in('where', :with => @postcode)
click_button('Go!')
end
Then(/^I am told it is valid for (.*)$/) do |arg1|
expect(page.has_text? arg1).to eq true
end
4. I then run my "cucumber" again to see if it works. Now that I have steps defined, the selenium drivers I have in my source are going to act as a puppeteer to control Firefox - and thus the website is tested. Here's a sample output:

Reading that output (from an extended version wit four rather than two sets of data), I can see that four tests have passed and one has - intentionally - failed. Testing does require that - from time to time - you make things go wrong to check that it's really doing the noral tests correctly!
Gherkin source code - [here]
Ruby steps using Selenium - [here]
Alternative steps using Watir - [here]