Thursday, March 29, 2012

Passing Test Parameters on the Cucumber Command Line


When I was researching watir, watir-webdriver and cucumber, I came across a number of articles by Alister Scott.  One in particular was helpful in structuring my code. It talked about implementing page objects.

As I started writing Cucumber tests, I was also learning the architecture of my company's website.  We have a number of silo-ed sites, one for each client.  Some are using older versions of code, and most are using a newer version.  I needed a way to pass which site I was using.  While I was at it, I decided to pass in which browser I wanted to use (IE, FF, Chrome, etc), as well as the testing environment (QA, Staging, Prod, etc), and whether or not I want the browser to stay open.  I also wanted defaults in case someone ran this without passing a parameter.

case ENV['BROWSER']
  when 'ie', 'Internet Explorer'
    browser = Watir::Browser.new :ie
    browser_name = 'Internet Explorer'
  when 'ff', 'Firefox'
    browser = Watir::Browser.new :ff
    browser_name = 'Firefox'
  when 'chrome'
    browser = Watir::Browser.new :chrome
    browser_name = 'Chrome'
  when 'opera'
    browser = Watir::Browser.new :opera
    browser_name = 'Opera'
  when 'debug'
    debug_profile = Selenium::WebDriver::Firefox::Profile.new
    debug_profile.add_extension "firebug-1.9.1-fx.xpi"
    browser = Watir::Browser.new :firefox, :profile => debug_profile
    browser_name = 'Firefox (Firebug)'
  else
    browser = Watir::Browser.new :ie
    browser_name = 'Internet Explorer'
end

URLS = {     'production' => "https://www.trialnet.com/",
           'qa' => "https://qa.trialnet.com/",
           'staging' => "https://stage.trialnet.com/",
           'dev' => "https://devel.trialnet.com/"
}

if URLS[ENV['URL']].nil?
  environment = 'QA'
  url = URLS['qa']
else
  environment = ENV['URL'].upcase
  url = URLS[ENV['URL']]
end

if ENV['CLIENT'].nil?
  client = 'Client-A'
else
  client = ENV['CLIENT']
end

puts "Browser      " + browser_name
puts "URL          " + url
puts "Environment: " + environment
puts "Client:      " + client

Before do
    @browser = browser
  @test_env = { :browser => browser,
                :browser_name => browser_name,
                :url => url,
                :env => environment,
                :client => client,
                :login => nil
  }
end 

Then I can just add the following on the command line or in my cucumber yaml file:

default: END_STATE=open URL=qa CLIENT=My-Client BROWSER=ie --format pretty --format html --out results.html -r features -r features\support -r features\step_definitions -r features\pages

END_STATE=open indicates I want to leave my browser open.  I decided to call it END_STATE in case I come up with other things I want to happen at the end of a run.  Any other value defaults to shutting the browser.

URL= indicates the environment I want to use.  If I can't resolve the environment passed, I default to the qa environment to make sure this doesn't accidentally get run in production.

BROWSER= tells me what browser to use.  The default is IE, because  95% of our customers use IE.  However, I may make it a headless browser in the future.

CLIENT= indicates the customer site I want to test.  Currently I'm limited to one client per execution, but for now that's ok.  I have a default set to one of the more generic sites, in case it isn't defined.  This is mainly for the developers that may use this on their own and don't care what site we're on.  In addition to choosing the site, I can call this code to deal with buttons that are named differently on older clients.

When /^I upload invoice "(.*)"$/ do |filename|
  @upload_invoice_page = UploadInvoicePage.new(@test_env)
  @upload_invoice_page.upload_file(filename)
end


In the above cucumber step you can see that I pass a @test_env instance instead of a @browser instance.  Then in my page object I use it as follows:

class UploadInvoicePage

  def initialize(test_env)
    @browser = test_env[:browser]
    case test_env[:client]
      when 'Old-Client-Named-Bob'
        @invoice_file       = @browser.file_field(:id => 'invoice_file')
        @upload_button      = @browser.div(:class => 'actionbar').image(:alt => 'Upload')
      else
        @invoice_file       = @browser.file_field(:name => 'file')
        @upload_button      = @browser.input(:type => 'image', :alt => 'Upload')
    end

    @upload_complete_button = @browser.div(:id => 'upload-footer').link
  end

  def upload_file(file_name)
    self.invoice_file.set(file_name)
    self.upload_button.click
    self.upload_complete_button.when_present.click
  end

end


The invoice_file and upload_button objects are set based on which client site I am on.  As sites are deprecated, I can remove the case statements and they should continue to work without any additional refactoring on my part.

Tuesday, March 27, 2012

Using Firebug with Watir-Webdriver on Windows

I wrote some tests using watir-webdriver in IE, and when I ran them in Firefox, I had issues.  Sadly, I could not get Firebug to come up.  It seemed to be disabled.  Doing some research indicated that I needed to create a profile that could use Firebug.  It took some digging, but I finally got it to work.

The elusive firebug.
1.) Download the firebug.xpi file from https://addons.mozilla.org/en-US/firefox/addon/firebug/ by right-clicking on the + Add to Firefox button and saving the file.
2.) Place the firebug.xpi file in the root directory of your cucumber (or watir-webdriver) directory - the same level as your cucumber.yml.  (I did this just so I wouldn't have / \ issues going between linux and Windows.  It's a quick and dirty solution.)
3.) Add the following code to your env.rb or wherever you are instantiating your browser object:

    debug_profile = Selenium::WebDriver::Firefox::Profile.new
    debug_profile.add_extension "firebug-1.9.1-fx.xpi"
    browser = Watir::Browser.new :firefox, :profile => debug_profile 

Now when you run watir-webdriver, you will find you have Firebug available.

One gotcha I encountered was I saved the firebug.xpi file using Chrome.  It was corrupted, and I was getting an error about the zipfile not having an end.  So if you see that, re-download the file.  Preferably using Firefox.