Main Content

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 Ellis

This 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]