Page Object Pattern
RSSS

Page Object Pattern, the term that selenium users keep buzzing. Page object is a design pattern that can be implemented as a selenium best practices. The functionality classes (PageObjects) in this design represent a logical relationship between the pages of the application.

  • The Page Object pattern represents the screens of your web app as a series of objects and encapsulates the features represented by a page.
  • It allows us to model the UI in our tests.
  • A page object is an object-oriented class that serves as an interface to a page of your AUT.

More on Page Object Pattern at Selenium wiki. Some of the advantages of page object pattern as listed below,

  • Reduces the duplication of code
  •  Makes tests more readable and robust
  • Improves the maintainability of tests, particularly when there is frequent change in the AUT. (Useful in Agile methodology based projects)

Enough of theory, lets get into practical implementation.

Page Object, which models the Google search page:


public class GoogleSearchPage {

protected WebDriver driver;
private WebElement q;
private WebElement btn;

public GoogleSearchPage(WebDriver driver) {
this.driver = driver;
}
public void open(String url) {
driver.get(url);
}
public void close() {
driver.quit();
}
public String getTitle() {
return driver.getTitle();
}
public void searchFor(String searchTerm) {
q.sendKeys(searchTerm);
btn.click();
}
public void typeSearchTerm(String searchTerm) {
q.sendKeys(searchTerm);
}
public void clickOnSearch() {
btn.click();
}
}

WebDriver provides a way to map it to a real web page. The PageFactory class provides a convenient way of initializing and mapping the Page Object fields.


public class WhenAUserSearchesOnGoogle {

private GoogleSearchPage page;

@Before
public void openTheBrowser() {
page = PageFactory.initElements(new FirefoxDriver(), GoogleSearchPage.class);
page.open("http://google.co.in/");
}

@After
public void closeTheBrowser() {
page.close();
}

@Test
public void whenTheUserSearchesForSeleniumTheResultPageTitleShouldContainCats() {
page.searchFor("selenium");
assertThat(page.getTitle(), containsString("selenium") );
}
}

By default, it will map Page Object properties to fields with matching ids or names, so the example given here will work fine out of the box. But sometimes we need more control over identifying elements in the HTML page and mapping them to our Page Object fields. One way to do this is to use the @FindBy annotation, as shown in the following code:


public class GoogleSearchPage {

protected WebDriver driver;

@FindBy(name="q")
private WebElement searchField;

@FindBy(name="btnG")
private WebElement searchButton;

public AnnotatedGoogleSearchPage(WebDriver driver) {
this.driver = driver;
}

public void open(String url) {
driver.get(url);
}

public void close() {
driver.quit();
}

public String getTitle() {
return driver.getTitle();
}

public void searchFor(String searchTerm) {
searchField.sendKeys(searchTerm);
searchButton.click();
}

public void typeSearchTerm(String searchTerm) {
searchField.sendKeys(searchTerm);
}

public void clickOnSearch() {
searchButton.click();
}
}

11 thoughts on “Page Object Pattern

  1. March 19, 2013 at 8:10 pm

    This article was very useful, it makes clear to understand the purposes and the use of Page Objects. Thanks a lot. But I think that in the last piece of code the class name should be “AnnotatedGoogleSearchPage” instead of “GoogleSearchPage” to be the same name as the constructor method.

  2. Amit
    November 22, 2013 at 7:22 am

    Hi,
    Its a nice blog and I have learn about creating POM from this bog. Its a really a good blog. However I have a doubt in framework using POM.

    My page objects are below:-
    loginpageObjects.class, homepageObjects.class, editpostObjects.class and updateProfileObjects.class
    Here loginpageObjects.class is extending homepageObjects.class and homepageObjects.class is extending updateProfileObjects.class and updateProfileObjects.class is extending Actiondriver.class (which is in separate package hving all the actions defined like clicking button typing in text boxes etc…)
    Now in homepageObjects.class the below code is:-
    package pageObjects;

    //public class homepageObjects extends actionsDriver{
    public class homepageObjects extends updateprofileObjects{
    public homepageObjects(WebDriver driver) {
    super(driver);
    }
    homepageElements homepageelements_Obj = new homepageElements();
    public homepageObjects clickSignoutBtn(){
    click(homepageelements_Obj.clickSignOut());
    return new homepageObjects(driver);
    }
    public updateprofileObjects click_UpdateMyProfile_Link(){
    //homepageelements_Obj.click_updateMyProfile();
    click(homepageelements_Obj.click_updateMyProfile());
    return new updateprofileObjects(driver);
    }
    }

    Here “homepageObjects” is extending “updateprofileObjects.class” and hence on clicking “updateprofile_link” methiod, I have returned updateprofileObjects.
    On the same home page, there is another link (EditPost link) to goto my posted adds (it’s a new page to which I will land where I can edit my created add) and for this I have created a new pageobject called “editinforObjects.class”.
    Now my question is that how can I create a method for clicking above “EditPost” link of Homepage and return this “EditInfoObjects.class” object.
    DO I need to extend the class “editinfoObjects.class” in “homepageObjects.class”. But “homepageObjects.class” is already extending “updateprofileObjects.class”. SO kindly let me know how can I achieve this.
    It would be really very helpful.

    Thanks
    Amit

  3. Michael
    January 29, 2014 at 4:52 pm

    I really love the page object pattern as the right abstraction to do surface tests, but I really don’t like seleniums implementation of that pattern, cause I have to write to much boilerplate code and don’t have the flexibility I need, so I created another framework based on Webdriver that lets you create PageObjects just by annotating interfaces: popperfw.org/

    1. asma labadi
      August 5, 2014 at 5:53 am

      Hi Michael can u share ur experience how to create your temlate

  4. Mukesh Otwani
    February 20, 2014 at 12:04 pm

    I really liked your blog now I got the concept of POM also but i am getting NullPointerException in thi line
    page.open(“http://google.co.in/”);

  5. March 29, 2014 at 1:10 pm

    It’s truly a nice and helpful piece of information. I’m glad that you just shared this
    helpful information with us. Please keep us up to date like this.
    Thank you for sharing.

  6. April 9, 2014 at 2:03 am

    Thanks for your marvelous posting! I seriously enjoyed reading it, you will be a great author.I will remember to
    bookmark your blog and will eventually come back from now on.
    I want to encourage continue your great work, have a nice evening!

  7. May 8, 2014 at 1:47 pm

    I’ve written about DRY page objects over at my blog: http://burdettelamar.wordpress.com/2014/03/21/keep-your-page-objects-dry/

  8. Jim
    June 27, 2014 at 8:56 am

    Hi, thanks for sharing your blog. Your page object patterns make my web page more beautiful and unique. It increase my web page quality and understandability.

  9. August 4, 2014 at 4:52 am

    Nice post. But I do wonder, it seems you have some redundant code in your example, for which you could have used some code reuse – with searchFor() implementation simply calling typeSearchTerm() followed by clickOnSearch() for more optimal code.

    And FYI, I adapted your example here for Robot Framework in a non code approach to page objects. So thanks for an example I could port over.

    https://github.com/daluu/robotframework-simple-page-object-example

Leave a Reply

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