Improving my WatirMelonCucumber page object framework

I’ve been working on some improvements to my WatirMelonCucumber page object framework, partly inspired by the SpecDriver C# framework I put together, and also inspired by a work colleague who’s especially good at ruby and meta-programming.

Base Page Class to inherit from

The first improvement is adding a base page class that all pages defined inherit stuff from. This means I don’t have to write an initialize for every page, as the base page class initializes each page automagically. This base page class can also navigate to the selected pages direct if needed, check for the appearance of a certain element if needed, and check the title is correctly displayed, again, if needed. Lastly, the base page class catches any methods that are missing and throws these to the browser, which means you can call browser methods such as title, and text at the page level.

class BasePageClass
  include WatirWebDriverHelper

  def initialize browser, visit = false
    @browser = browser
    goto if visit
    expected_element if respond_to? :expected_element
    has_expected_title? if respond_to? :has_expected_title?

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

Watir Page Helper Mixin

I originally saw the Watir Helper idea in Jeff Morgan’s cucumber framework, which I have used here. I have made quite a few changes, not only to support more elements, but also to allow passing in blocks to the helper methods. This helper is included in the base page class, and therefore is accessible in any page defined that inherits from the base page class.

Update: 5th May: See my watir-page-helper gem to include this automatically.

Resulting page model example
The combination of these two improvements mentioned, now mean the actual page classes are nice and neat. For example:

class GoogleHomePage < SearchPageClass

  direct_url ""
  expected_title "Google"

  button :google_search, :name => "btnG"

  def search_for term = term
    google_search, false)

Ruby & Browser Support

I have changed the framework to use Chrome, since it’s so fast, but that’s easily configurable in env.rb, and watir-webdriver headless instead of Celerity. This means JRuby is not needed, and it can run under Ruby 1.9.2.


By introducing the base page class, and the watir page helper methods, it means the resulting page models are short, simple and easy to understand. There is a lot less repetition, for example, not including the watir helper in every page, as it’s included in the base, and also not needing an initialize for each page that essentially does the same thing.

Let me know what you think.

Author: Alister Scott

Alister is an Excellence Wrangler for Automattic.

10 thoughts on “Improving my WatirMelonCucumber page object framework”

  1. Wow, i was really enjoying Jeff Morgan’s cucumber framework and especially the WatirHelper module. Your approach looks even better. Thank you for sharing :)



  2. Hi Alister,

    Really great blog you have written. I have been keeping up to date with what you have written in the past and this blog will really help me improve my framework.
    One question I do have though is that you have mentioned that you are now using watir-webdriver headless. Is it possible for you to share the code on how to get this working? Currently my test can only run in the different browsers supported by webdriver for a mac. e.g. Firefox Chrome etc…
    I would lvoe to get my suite running headless but after searching the net I am none the wiser on how to do this.
    What do i change in the env.rb file? or what other files do i need to change? any help would be greatly appreciated.
    If you wish to email me some code then please do so on:

    if you need more info please let me know and ill try my hardest to provide it.

    Thanks in advance,
    Kind regards,
    Usman Hussain


      1. Thank you for the reply. I have now got it working which is brilliant news. But there is one problem that I am encountering… That is when I try to run the tests headless with Javascript turned on.
        First I tried this:
        @browser =, :url => “”, :desired_capabilities => :htmlunit)
        This worked without any problems, But when I tried this (from your blog):
        capabilities = WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true)
        @browser =, :url => “”, :desired_capabilities => capabilities)
        I am getting the following error:
        “no such file to load — webdriver (LoadError)”

        I am requiring “watir-webdriver” so would have assumed webdriver would also be loaded…

        Have you come accross this problem before? I am searching google as well so will let you know if I find anything.

        Again many thanks for your help so far.

        Kind regards,
        Usman Hussain


  3. Thanks very much for your effort. I really like what you’re doing here. Can you please provide an expanded example of how one might use the block capabilities you have in your gem?



    1. Sure, see this page:
      It has a select list in a ‘search category’ div that changes dynamically depending on what is selected in the first select list, therefore it’s the first select list in a div.
      Therefore, the definition looks like:

      select_list :sub_category do |browser|
          browser.div(:class => "search-category").select_list

      I don’t think there’s a way to do this is selenium.
      The whole page is defined here:


  4. Hello,

    I’m trying to use your great framework for our project but faced with such error if try to start feature

    undefined method `capitalize’ for :Home:Symbol (NoMethodError)
    ./support/env.rb:16:in `on’
    ./support/env.rb:12:in `visit’
    ./step_definitions/search_steps.rb:3:in `/^I am on the (.+) Home Page$/’
    internet_search.feature:7:in `Given I am on the “Google” Home Page’

    Please advise!

    I use Ruby 1.8.7 (not JRuby)



    1. It is because ruby 1.8.7 doesn’t support capitalize for symbols. I have updated the code which should work correctly now.
      I use 1.9.2, and this worked fine before.
      If you are using git, please use “git pull” and run again.


Comments are closed.