Selenium WebDriver: Page Object Pattern and PageFactory

Written by   |  Friday, 24 February 2012
Rate this item
(11 votes)



How does it work?

Page Object Pattern is a pattern that displays user interface as a class. In addition to user interface, functionality of the page is also described in this class. This provides a bridge between page and test.

 

 

Why should it be used?

 

Here are the main advantages of Page Object Pattern using:

  1. Simple and clear tests.

  2. Good support of tests, because everything is stored in one place.

  3. Easy creation of new tests. In fact, tests can be created by a person not knowing the features of automation tools.

Simple example of using Page Object Pattern and PageFactory in Selenium WebDriver

So we have the page LoginPage shown on the image above.

This page contains the following elements:

    1. login field

    2. password field

    3. button «LoginButton»

And the following functionality:

  1. to enter something into login field

  2. to enter something into password field

  3. to click on the button «LoginButton»

  4. to log in to the application

So our class describing LoginPage will look the following way:

public class LoginPage {
final WebDriver driver;
@FindBy(how = How.NAME, using = "login")
private WebElement loginEdit;
@FindBy(how = How.NAME, using = "pass")
private WebElement passwordEdit;
@FindBy(how = How.NAME, using = "button")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void enterLogin(String login) {
loginEdit.clear();
loginEdit.send(login);
}
public void enterPassword(String password) {
loginEdit.clear();
passwordEdit.send(password);
}
public void clickLoginButton() {
loginButton.click();
}
public HomePage login(String login, String password) {
enterLogin(login);
enterPassword(password);
clickLoginButton();
return PageFactory.initElements(driver, HomePage.class);
}
}

Yes, we develop apps!

No ads, just a really great application development service. Contact us now and get  a free quote.

power

call to action block1

 

 

Before we’ll examine the above code, let’s look at another HomePage page that we enter after clicking the login button.

This page contains the following elements:

  1. Text «Hello!»

  2. button «ExitButton»

And the following functionality:

  1. Logout

So, our class describing HomePage will look the following way:

public class HomePage {
final WebDriver driver;
@FindBy(how = How.NAME, using = "text")
private WebElement helloText;
@FindBy(how = How.NAME, using = "exit")
private WebElement exitButton;
public HomePage(WebDriver driver) {
this.driver = driver;
}
public void clickExitButton() {
exitButton.click();
}
public LoginPage logout() {
clickExitButton();
return PageFactory.initElements(driver, LoginPage.class);
}
}

Now let’s look at our code:

public class HomePage {

declare a class HomePage

final WebDriver driver;

declare our driver

@FindBy(how = How.NAME, using = "text")
private WebElement helloText;
@FindBy(how = How.NAME, using = "exit")
private WebElement exitButton;

here we use the annotation FindBy for making the WebElement object to know to which element it belongs on web page (for example helloText belongs to the element whose attribute is name = text, and exitButton belongs to the element whose attribute is name = exit)

public HomePage(WebDriver driver) {

constructor of our class must take one WebDriver object

public void clickExitButton() {

public LoginPage logout() {

functionality described above

public LoginPage logout() {

this method returns to us the page class to which we go after a successful logout

clickExitButton();

here we describe the main steps of logout

return PageFactory.initElements(driver, HomePage.class);

and so we return the page class initialized with PageFactory.

The same situation is with LoginPage.

It seems to be easy.

How will our test look?

public class LoginLogoutTest extends TestCase {
WebDriver driver;
private static String login = "admin";
private static String pass = "test";
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
}
@Test
public void testLoginLogout() throws Exception {
driver.get("yousite.ru");
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
HomePage homePage = loginPage.login(login, pass);
LoginPage loginPageAfterLogout = homePage.logout();
}
@After
public void tearDown() throws Exception {
driver.quit();
}
}

As we see we’ve got a simple and intuitive description of our test:

LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
HomePage homePage = loginPage.login(login, pass);
LoginPage loginPageAfterLogout = homePage.logout();

Why use PageFactory?

For example, in the above classes, we used the following description of the elements on the page:

@FindBy(how = How.NAME, using = "text")
private WebElement helloText;

But as we use PageFactory, code can be written as follows:

private WebElement text;

where text will refer to an element with the attribute name = text

What’s going on?

When we initialize the page using PageFactory, then, if annotation FindBy is not specified, PageFactory searches for elements on the page which name or id attributes match the name of WebElement.

As a result, we actually do not have to worry about searching for elements on the page. If the element will appear on the page, so when we turn to it, it will be initialized.

Also, if we know that element is always present on the page, it is best to use the following declaration:

@FindBy(how = How.NAME, using = "text")
@CacheLookup
private WebElement helloText;

If we don’t do it, then every time when we turn to our element, WebDriver will check if the element is present on the page.

What now?

In this article, I gave a simple example of using Page Object Pattern and PageFactory in Selenium WebDriver. If you are interested in this method, then the following links will be helpful for you:

  1. http://code.google.com/p/selenium/wiki/PageObjects

  2. http://code.google.com/p/selenium/wiki/PageFactory

  3. http://code.google.com/p/selenium/wiki/DesignPatterns

If you’d like we apply our experience and knowledge to make your software better, you might be interested in our software testing service.

Read 12563 times Last modified on Monday, 04 March 2013
Vadim Chadyuk

I'm a QA specialist at a software development company IntexSoft. I have 1+ year experience of testing web based, desktop and mobile applications. I am proficient in test case creation, test execution and bug tracking. I am also experienced in black box testing, white box testing, functional and GUI testing, regression and performance testing. Most of all, I enjoy learning new tools and technologies.

Add comment


Security code
Refresh