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:

[sourcecode language="java" wraplines="false" collapse="false"]
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();
}
}
[/sourcecode]

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.

[sourcecode language="java" wraplines="false" collapse="false"]
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") );
}
}
[/sourcecode]

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:

[sourcecode language="java" wraplines="false" collapse="false"]
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();
}
}
[/sourcecode]

6 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/

  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.

Leave a Reply

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