Guest Post: Designing a Ruby-based Sauce Test Automation Framework Pt. 2

Posted by Bill McGee in Guest Blog PostsRubySoftware Development & Testing

Designing a Ruby-based Sauce Test Automation Framework – Implementing it on Ruby using Page Object Pattern
 

In the first part of this blog series, we defined Page Object Pattern and also familiarized ourselves with the various building blocks of the Ruby-based test automation framework. Now that, we have realized the benefits of using such a framework, let us try implementing a Simple Test Framework on Ruby using Page Object Pattern. Implementing a Simple Test Framework on Ruby using Page Object Pattern
In the following section, we will implement a simple Selenium test framework using Page object pattern. Our framework contains Base classes for Test, Action, Page and Page element objects. Next, we will write a few very simple test cases for:

  1. Verifying the page title on a web page
  2. b. Test a form by filling the data elements in the form and testing a successful submit.

Test Base Class

First, let’s do a walkthrough of the Test Base class.

  1. Include the Selenium-webdriver Rubygem which is used to connect the testing framework with Selenium web driver.
  2. The start_browser() function invokes the Firefox browser with required options such as OS type, browser version, etc.

>Please Note: For testing purposes we have set the default browser as Firefox on Linux, but we can make this dynamic by passing the corresponding parameters.

  1. This class also has other utility functions such as
    1. get_data() - to make Database connections and retrieve data
    2. launch_url() - to launch a new URL on the browser
    3. switch_to_frame() - to switch between active frames / windows.
require 'rubygems'
require 'selenium-webdriver'

class SeleniumTestBase

def initialize (webDriver) @driver = webDriver end

#this function starts the selenium webDriver on Firefox browser type #we can make it dynamic by using the params

def start_browser(browser_type,platform,version)

caps = Selenium::WebDriver::Remote::Capabilities.firefox
caps.version = "5"
caps.platform = :LINUX
caps[:name] = "Testing Selenium 2 with Ruby on SauceLabs Environment"

@driver = Selenium::WebDriver.for(
  :remote,
  :url => "<Use SauceLabs URL with appropriate key>",
  :desired_capabilities => caps
)

end

def switch_to_window(handle) @driver.switch_to.window handle end

def switch_to_frame (handle) @driver.switch.frame handle end

def launch_url ( url) @driver.navigate.to url end

def get_data(conn_string,sql1 ) #some sql statements end

def refresh @driver.get @driver.url end

def teardown @driver.quit end end

Please note one of the advantages of writing a separate Test Base class is that it uses the underlying driver implementation from the Test cases. Therefore, if we want to experiment with a new Driver version or even a completely new Driver, then the TestBase is the only class that will change leaving other parts of the framework untouched. In a later section, we will show how one can create a project specific TestBase class which extends the main TestBase class. This will allow individual project teams to make project specific changes to the base class.

Action Base Class

>Actions Base classes are responsible for the following:

  1. Executing steps required to run the test
  2. Inserting / Updating data elements and changing the state of the application while executing the test
  3. Reverting the changes made during the tests (for eg., rolling back the changes made on the database)
  4. Page operations such as navigating to a page, refreshing, switching across different frames and windows, etc.
class SeleniumActionBase

def initialize (webDriver) @driver =  webDriver end

def get_data(conn_string,sql1 ) #connect to db #execute sql to retrieve data end

def start_browser(browser_type) #override end

def switch_to_window(handle) #override end

def switch_to_frame (handle)
#override end

def launch_url (url) #override end

def refresh #override end end

The Page Class refers to actual web pages on the application that we want to test and essentially consists of a group of Page Elements. This class also defines a variable called BrowserIndex. Different browsers implement the locator start indexes differently and this variable can be used to handle the different implementations based on the browser type.

class SeleniumPageBase

attr_reader :browserIndex

def initialize ( webDriver) @driver = webDriver @browserIndex  = 1 end

end

Page Element Base Class

The Page Element class is responsible for the following:

  1. Handle the actual interactions between the tests and the web pages.
  2. Wait for a particular page element to load (especially in case of Ajax)
  3. Provide specific error messages to describe why a particular page interaction failed.
class SeleniumPageElement

def initialize(webDriver) @driver = webDriver end

def waiting_get(seconds = 5, errorMessage = "") wait = Selenium::WebDriver::Wait.new(:timeout => seconds) wait.until { @myDriver.find_element(:id, @myBy) } end

def click(seconds = 5, errorMessage = "") waiting_get(seconds, errorMessage).click(); end

def load_element(locator,val,errorMessage ='') @myBy = locator @element = find_element_id @element.send_keys val end

def submit @element.submit end

def get_response @driver.find_element(:id, 'your_comments') end

protected

def find_element_id begin return  @driver.find_element(:id, @myBy) rescue  Exception=>e raise e end end end

This guest blog post was written by Vinodh Balaji Sridharan and Ganesh Kaliannan, Neev Technologies

Discuss: Guest Post: Designing a Ruby-based Sauce Test Automation Framework Pt. 2
0 Comments

Free Trial

Get access to a free 14-day trial version, or contact Sales for more information.