What is whirlwind <https://github.com/ccyphers/whirlwind>?  It adds a few
aspects to cucumber, rspec and watir, resulting in sensible best practices
where one can write more automated test cases in a reliable way without the
framework getting in the user's way.  This is accomplished by having flow
objects automatically created for you so there's no manual steps such as:

@demo_homepage = Demo::HomePage.new.

>From rspec definitions and flows you can call screen_shot('some image
description') and the image will be included in the html report residing
under sites/<site_name>/results.  See an example report
https://cyberconnect.biz/opensource/whirlwind_ex.html.

With best practice of organizing the fixture data by site and test
environment you are not limited to accessing one site from any given feature
that's executing.  For example, say you have two automated test sites,
'SITE1' and 'GMAIL'.  Within both sites you would have defined flows and
elements along with associated fixtures.  Lets say you have a flows defined
under SITE1::HomePage and GMAIL::HomePage.  Anytime you run a feature set
you will automatically have access to instance variables @site1_homepage and
@gmail_homepage. You would also have defined fixture data under
sites/SITE1/conf/base_urls.yml and sites/GMAIL/conf/base_urls.yml.  Now if
you need to navigate between the two sites you could do something like:

@browser.go(@test_data['SITE1'][:base_urls][$environment][:home_page])

Do some actions which results in an email being sent where you now need to
navigate to gmail and check for the confirmation:

@browser.go(@test_data['GMAIL'][:base_urls][$environment][:home_page])

where your base_urls.yml would have something like
:dev:
 :home_page: 'http://someurl.for.dev'
:test:
 :home_page: 'http://someurl.for.test'
:prod:
 :home_page: 'http://someurl.for.prod'

Element Conventions:
Organize your elements into meaningful namespaces such as:

module Demo
  module Elements
    class Tabs
      include RSpec::Core::DSL # always include this line in all element
classes
    end
    class Header
      include RSpec::Core::DSL
    end
    class Footer
      include RSpec::Core::DSL
    end
    class Dialogs
      include RSpec::Core::DSL
    end
  end
end

Create as many element files as needed for your site under
sites/<site_name>/elements.  Given the above example name the file something
like sites/demo/elements/demo_common_elements.rb.  Now you have all your
common elements than can be accessed from multiple pages.  Lets take a look
at defining elements:
module Demo
  module Elements
    class Menu
      include RSpec::Core::DSL
      def initialize
        define_me(:full_menu_div) {@browser.div(:id, 'main_menu')}
        define_me(:actions) { full_menu_div.link(:text, 'Actions') }
        define_me(:test_alert) {
          actions.mouseover
          full_menu_div.link(:text, 'Test Alert')
        }
        define_me(:test_dialog) {
          actions.mouseover
          full_menu_div.link(:text, 'Test Dialog')
        }
      end
    end
  end
end

Flows:
Since flow objects are dynamically created for you it's urgent that you must
have only one module and class per file.  Like elements you can have as many
files under sites/<site_name>/flows as required.  Notice in the example
below that you instantiate a reference to an element definition.  Always use
the convention as setting the instance variable to @elements.  This is
needed as when the flow instances are automatically created for you it will
expect this format.  Remember all the common elements?  Within your
Demo::Elements::HomePage we instantiated instances
to Demo::Elements::Tabs, Demo::Elements::Menu and Demo::Elements::Dialogs so
that we can access them via items such as
@elements.tabs.registration.element_name.

module Demo
  class HomePage
    include RSpec::Core::DSL
    attr_reader :elements
    def initialize
      @elements = Demo::Elements::HomePage.new
    end

    def home

@browser.goto(@test_data['demo'][:base_urls][$environment][:demo_home])
      @elements.tabs.registration.wait_until_present
      screen_shot('Landed on Home Page')
    end

    def registration
      home
      @elements.tabs.registration.wait_until_present
      @elements.tabs.registration.click
      @demo_registrationpage.elements.step_1_next.wait_until_present
      screen_shot('Landed on Registration Page')
    end

  end
end

What other magic is done for you?  All the instance variables referencing
the flows are available from each other.  For example, if you are a method
in the Demo::HomePage#method but need to call a method in the
Demo::RegistrationPage flow you can  access @demo_registrationpage from
within the instance of @demo_homepage.  You will notice this above in
Demo::HomePage#registration
@demo_registrationpage.elements.step_1_next.wait_until_present.
 The user doesn't have to wire this up, instance variables have been created
for you at runtime.

Happy Testing
Cliff.

-- 
Before posting, please read http://watir.com/support. In short: search before 
you ask, be nice.

[email protected]
http://groups.google.com/group/watir-general
[email protected]

Reply via email to