Cucumber Bing and Google

Reducing step explosion by decoupling Cucumber steps from your GUI

Yesterday I wrote about creating a simple page object pattern framework in Cucumber that uses Watir to drive browsers.

Ben Biddington left an excellent comment:

“The thing I like about this pattern is you could run the feature against a completely different search engine by just creating a new page object impl.

This prevents the common “step explosion” problem all too common with cucumber suites.”

Ben highlights an important point, the page object pattern decouples your cucumber steps from your GUI, helping to reduce “step explosion”.

To demonstrate this concept, I very easily modified my feature I wrote yesterday to test both Google and Bing, by using the same step definitions, but using scenario outlines instead of scenarios.

Feature: Internet Search
  As a casual internet user
  I want to find some information about watir, and do a quick conversion
  So that I can be knowledgeable being

  Scenario Outline: Search for Watir
    Given I am on the  Home Page
    When I search for "Watir"
    Then I should see at least  results
    Scenarios:
      | search engine | expected number of  |
      | Google        | 100,000             |
      | Bing          |  85,000             |

  Scenario Outline: Do a unit conversion
    Given I am on the  Home Page
    When I convert 10 cm to inches
    Then I should see the conversion result ""
    Scenarios:
      | search engine | as expected                         |
      | Google        | 10 centimeters = 3.93700787 inches  |
      | Bing          | 10 centimetres = 3.937007874 inches |

  Scenario Outline: Do a search using data specified externally
    Given I am on the  Home Page
    When I search for a ridiculously small number of results
    Then I should see at most 5 results
    Scenarios:
      | search engine |
      | Google        |
      | Bing          |

The way I had written my step definitions before weren’t tied to a particular page (besides the naming, which I simply refactored), so all that was needed was to write two new page.rb files with the same methods as the Google pages.

Bing’s home page:

class BingHomePage

  attr_accessor :search_field, :bing_search_button

  URLS = { :production => "http://www.bing.com/" }

  def initialize(browser)
    @browser = browser
    @search_field         = @browser.text_field(:name => "q")
    @bing_search_button  = @browser.button(:name => "go")
  end

  def method_missing(sym, *args, &block)
    @browser.send sym, *args, &block
  end

  def visit
    @browser.goto URLS[:production]
  end

  def search_for term
    self.search_field.set term
    self.bing_search_button.click
    bing_results_page = BingResultsPage.new(browser)
    bing_results_page.results.wait_until_present if WEBDRIVER
    bing_results_page
  end

and, Bing’s results page:

class BingResultsPage

  attr_accessor :results, :conversion_result

  def initialize(browser)
    @browser = browser
    @results = @browser.span(:id => "count")
    @conversion_result = @browser.span(:class => "sc_bigLine")
  end

  def method_missing(sym, *args, &block)
    @browser.send sym, *args, &block
  end

  def number_search_results
    result = /^[\s\w-]* of ([\d,]+) results$/.match(@results.text)
    raise "Could not determine number of search results from: '#{@results.text}'" if not result
    result.captures[0].gsub(",","").to_i
  end

end

Once I had these pages in place, I didn’t have to require them or anything else, as this is done by Cucumber, so I could now run my cucumber command and get results from two different search engines: Bing and Google. The feature highlighted some subtle differences in how they work: Google had more hits, Bing uses the Australian spelling of centimetres, and adds one more decimal place of precision to conversions.

Summary

As Ben pointed out, and I have demonstrated, by using a page object pattern, you can decouple your steps from your GUI. This allows you to switch GUIs, or indeed testing methods, which in our involved switching search engines, without changing or adding more step definitions, reducing “step explosion”.

Source Code

I have pushed all changes to GitHub: https://github.com/alisterscott/WatirMelonCucumber

Results

2 thoughts on “Reducing step explosion by decoupling Cucumber steps from your GUI

  1. Nice posts and nice lightweight framework, Alister! Thank you.

    As many other people, we are using very similar approach at Expedia quite for a while. And I really like a nice fit of page objects pattern with cucumber. We have also created some other good small bits in this pattern, e.g. a repo of pages/widgets using Composite and some other design patterns, I hope I will find time to write few posts about it.

    Anyway, just wanted to point out – you have too much duplication in your google/bing pages, mate!! :) But I really love how you are gaining one additional level of reusability: not only reusable steps, but the whole scenarios. Coolio.

Comments are closed.