20

I am a beginner in learning selenium Webdriver. I am not able to understand how page object and factory models works and how it can be beneficial?

Kindly help me explain it with detailed explanation.

14

PageObjects

The code of automated test cases should be easy to understand and not too complex. If a test fails, we want to know why and this as soon as possible. To allow this exists PageObjects. PageObjects are classes that contains WebElements and every actions associated with those.

A PageObject looks like this:

class HomePage {

    WebDriver driver;

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

    // Find a single element
    @FindBy(id="home-menu-entry")
    WebElement homeMenuEntry;

    public void clickHomeMenuEntry() {
        homeMenuEntry.click();
    }

    // Find several elements
    @FindBy(className="menu-entry")
    List<WebElement> menuEntries;

   // More actions and elements
}

Usage of PageFactory and PageObject

class TestSomething {

    public void testMethod() {

        // Initial driver.

        // Use PageFactory to init elements.
        HomePage hp = PageFactory.initElements(driver, HomePage.class);

        // Use PageObject to execute action.
        hp.clickHomeMenuEntry();

        // Assertions or more actions.

    }

}

You also can put the PageFactory.initElements(); into the constructor and create just an HomePage object instead of calling the PageFactory method.

Important: If you call initElements() all elements will be initialized, not later if you use them.

How to organize this?

I do the following: Each page has a PageObject, that represent these. But some components of a page are present on many pages. For this case I create for each component additional classes. Example:

  • Header.class
  • Footer.class
  • HomePage.class
  • ContactPage.class

Useful Links

  • for POM, where's the composition or inheritance? If you're dealing with fragments, how are you instantiating and initializing Header and Footer? – Thufir Dec 28 '18 at 14:37
  • @Thufir I do not know if there is one correct answer to this question, because it depends on the context. You have two options: Directly in the test, like "normal" page objects or as part of other page objects. I think it depends on how much do you use these components in your tests. – Twaldigas Jan 7 at 9:56
7

Page Factory Pattern is like an extension to Page Object Model , but Page Factory is much enhanced model. To start with, we just need to import package org.openqa.selenium.support.PageFactory

"Factory class can be used to make using Page Objects simpler and easier".

We use Page Factory pattern to initialize web elements which are defined in Page Objects.

We should initialize page objects using initElements() method from PageFactory Class as below, Once we call initElements() method, all elements will get initialized. PageFactory.initElements() static method takes the driver instance of the given class and the class type, and returns a Page Object with its fields fully initialized.

public HompePage(WebDriver driver) 
{           
   this.driver = driver; 
   PageFactory.initElements(driver, this);
}

Now question arise why we use Constructor?
Solution is=> We should preferably use a constructor which takes a WebDriver instance as its only argument or falling back on a no-arg constructor. An exception will be thrown if the class cannot be instantiated.
Page Factory will initialize every WebElement variable with a reference to a corresponding element on the actual web page based on “locators” defined.

Check below code by using Simple POM

public class BasePage 
{
private By username = By.id("username");
private By password = By.id("password");
private By loginBtn = By.name("loginbtn");

   public void userLogin(String userName, String password) 
   {
        driver.findElement(username).sendKeys("testuser");
        driver.findElement(password).sendKeys("testpassword");
        driver.findElement(loginBtn).click();
   }
}

By using using Page Factory:

public class BasePage {
  @FindBy(id= "username") private WebElement userName;
  @FindBy(id= "password") private WebElement password;
  @FindBy(id= "login") private WebElement loginBtn;

  public void userLogin(String userName, String password) {
    userName.sendKeys(userName);
    password.sendKeys(password);
    loginBtn.click();
  }
}
  • 1
    Please do not answer two questions with the same answer. If two questions require the exact same answer, they most likely are duplicates of each other. – corsiKa May 11 '16 at 16:24
  • with PageFactory, is only the first page initialized? Subsequent pages come initialized? – Thufir Dec 28 '18 at 0:40
3

In very simple terms, the explanation for page objects is as follows: A separate class (per page) which lists all the objects in a page and the allowed operations that can be performed by them can be created. And whenever you need to perform any tests on that particular page in your webapp, you write the test to first import the page, and thereafter, perform all the allowed functions on that page to execute your tests.

In effect, there is a clear definition of the page with its objects and actions that can be performed on each object, and a separation of the tests that use those methods.

A very obvious benefit would be that anyone who looks through the page object class will be able to know what objects reside on that page and what operation can be performed by each object. A test automation engineer working on contract or new to your project only needs to know the location of the page object class and can help automate tests without having to go through any extensive training.

Hope this gives a bit more clarity on page objects. Cheers!

1

Page objects is a well known design pattern, widely accepted by the automation engineers, to create separate class file for each page of the application to group all the elements as properties and their behaviors / business functionalities as methods of the class. But it might not be a great idea always, especially when the page has more / different sets of elements / complex element like a grid / calendar widget / a HTML table etc.

When you try to incorporate all the elements of a page in one single page class, it becomes too big to read, maintain etc. The class might contain too many responsibilities to handle. It should be restructured and broken into smaller classes.

I would expect my page objects to satisfy the Single Responsibility Responsible.

You can find more info here.

  • Please do not post the same answer to multiple questions. Also, you must disclose any affiliation in each post you create if you are promoting a product or external material. Additionally, the answer must answer the question without the external material/affiliation. I'm not convinced this meets that criteria. – corsiKa Sep 21 '16 at 19:44
  • @corsiKa, I am not trying to promote anything here. My answer seems to address the OP's question along with the accepted answer. Basically the answer is to follow certain principles while creating the page objects. – Vinoth S Sep 21 '16 at 19:52
  • It's a valuable resource, yes. It would be an improved resource, as a learning guide, if it didn't depend on graphene; in a sense, it promotes graphene -- which might be wonderful. But, it kinda does. Still, it's a good answer. And, a good link. – Thufir Dec 28 '18 at 15:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.