Using the Page Object Pattern with Robot Framework

I really don’t want to call this Page Objects, because Robot Framework (or simply RF) is a not an Object Oriented Framework.  So in the spirit of Page Objects and RF, I’ll call it Page Resources.  You probably have heard the Page Objects are good and that you should be using them in your automated tests. You are correct. However it might be a little unclear how you might accomplish this in RF.

 

The basic idea around Page Objects is that for each page in your web application you create a test object that encapsulates the things that are testable on that single page. The Page Object includes all of the functionality to interact with the system under test (SUT) via external third party libraries, like Selenium.

 

Typically what you will have right above the page object, is a piece of functionality that implements domain logic specific to your application like “Login in To Application”

 

Then your actual tests are built from these pieces of higher-level resources. This higher-level resource, for a lack of better word, I’ll call a “Service” because that’s what I would call it if this were an enterprise software application.

So think of this as a hierarchy, it looks like this:

At the highest level you have your test. Your test should include one or more Service Level Resources but should include any page level resources. That is because we want to isolate ourselves from changes to the SUT as much as possible. For example lets say something changes on the Home Page on your system. You may have to change your test. Which is normally is not a big deal. But lets say you have 200 tests. You may have to go to every single one of those tests and update them. That sucks! Especially since you don’t have the fancy refactoring IDEs that the developers have. But since you have isolated yourself via these layers of abstractions. You may only need to change a few Service Level resources.

 

An example high-level test could be something that logs into the application and checks the balance on the user’s account.

 

The next level is the service level. The service level contains helper keywords and includes and uses Page Resources. An example might be a helper that opens a web browser and logins into your application as a user. The user should not be defined but should be passed in via your high-level test case.

 

And finally the lowest level is the Page Resource. The page resource should be calling the Selenium2Library directory thus isolating your services and tests from changes in that Library. It could make it possible to switch that entire library out as well. Say when a Selenium3Library comes along or when someone writes a TonyWebdriver Library that just seems to work better. The Page Resource (PR) doesn’t know how to navigate to itself however it should be able to determine if it is truly on the page it represents.

 

So enough of all of this talk and lets see some examples. I’m going to do a simple Wikipedia test. Normally we have some parameters in the lower level tests but I will hard code everything so its more clear. The scenario I’m going to test is that I can get to the Nissan Motors Page via searching for a Nissan 240SX then clicking on a link on that page to get to the Nissan Motors (Corporate) Wikipedia page.

 

My example includes 3 Page Resources:

  • Wikipedia Home Page
  • Nissan 240SX Page on Wikipedia
  • The Nissan Motors Page on Wikipedia

 

There’s one higher-level service resource file and there is a single test. Lets look at the test first.

 

*** Settings ***
Test Teardown   Log TestRun

Documentation   A test suite with a single test for try page objects against the
...             Wikipedia Site

Resource        wikipedia-resource.txt

*** Test Cases ***

# This Test Case doesn't use the the Page Resources, it uses a higher level wikipedia resource
Goto Nissan Motors Page Via Searching and Clicking
        Search for Nissan 240SX on Wikipedia
        From Nissan 240SX page goto Nissan Motors Page
        #    [Teardown]  Close Browser

*** Keywords ***
Log TestRun
        ${html_src} =  Log Source
        Run Keyword If Test Failed  Create File   target/robot/myerror.html  ${html_src}
        #    Close Browser

So I have defined a single test case that uses two keywords from the Wikipedia service.

In the service resource I have

*** Settings ***

Documentation  A resource file containing the application specific keywords
...            that create our own domain specific language. This resource
...            implements a service resource
Library        Selenium2Library
Library        OperatingSystem
Resource       wikipedia-homepage.txt
Resource       wikipedia-nissan240sx-page.txt
Resource       wikipedia-nissan-motors-page.txt

*** Variables ***

${SERVER}               www.wikipedia.org
${BROWSER}              firefox
${DELAY}                0
${HOME PAGE URL}        http://${SERVER}

*** Keywords ***
# Uses Wikipedia and Nissan 240sx Page Resources
Search for Nissan 240SX on Wikipedia
        Open Browser To Wikipedia Home Page
        Search For Nissan 240SX
        Verify Nissan 240SX Page

# Uses Nissan 240sx and Nissan Motors Page Resources
From Nissan 240SX page goto Nissan Motors Page
        Click Link and goto Nissan Motors Page
        Verify Nissan Motors Page

 

 

In the service you can see I have included three page resources. The Wikipedia Home Page resource looks like this.

 

Library        Selenium2Library
Library        OperatingSystem

*** Keywords ***
Open Browser To Wikipedia Home Page
    Open Browser  ${HOME PAGE URL}  ${BROWSER}
    Maximize Browser Window
    Set Selenium Speed  ${DELAY}
    Title Should Be  Wikipedia

Search For Nissan 240SX
        Input Text  searchInput  Nissan 240sx
        Click Button  go

 

 

The first thing I need to call is “Open Browser To Wikipedia Home Page”. This keyword opens the browser and navigates to the Wikipedia home page. Right I don’t have a reason too, but I could pull that up a level to the service.  I like it here right now because it gives me a clean place to verify that I am actually on the homepage. See the “Tittle Should Be  Wikipedia” line? That verifies I am on the page. The Nissan 240sx page resource is pretty simple.

 

Library        Selenium2Library

*** Keywords ***
Verify Nissan 240SX Page
        Title Should Be  Nissan 240SX - Wikipedia, the free encyclopedia

Click Link and goto Nissan Motors Page
        Click Link  Nissan

 

It has a verify keyword and a click link keyword. The page resource as you might expect has had to make some assumptions about the SUT. It assumes that there is a link named “Nissan” on it that links to the Nissan corporate page. However anyone can change this page. Lets say they decide to rewrite this page a little and change that link to say “Manufacture” instead and the “Nissan” link goes to the Nissan Motorsports page. If you had 200 tests that had to get to the Nissan corporate page via this mechanism (searching and clicking) and you had flat tests that repeated this navigation method (because you are handy with the cut and paste), you would be changing 200 tests. However since you used the Page Resource pattern you only have a single file to change and more time for happy hour.

 

Feel free to contact me if you want a couple of all of the files and maven project that you can try out.

 

 

 

 

One Response to “Using the Page Object Pattern with Robot Framework”

  1. Good explanation of how the page object concept works with Robot Framework. You, and others reading this, may also be interested in a related post by Andreas Ebbert-Karroum:
    http://blog.codecentric.de/en/2010/07/how-to-structure-a-scalable-and-maintainable-acceptance-test-suite/

    PS: There seems to be “not” missing from this sentence: “Your test should include one or more Service Level Resources but should include any page level resources.”

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>