Page Object Model (POM) in Selenium

Page Object Model is an object design pattern implementations of Page factory in Selenium, where web pages are represented as java classes, and the various elements on the page are defined as a method on the PO classes. All reusable methods are stored in libraries.

  • Page Object Model is one of the implementations of java design patterns called Page Factory.
  • In selenium, we create a Page Object Modal class to develop and store the re-usable methods. These methods are nothing but Page Objects
  • Page Objects are nothing but web elements present on the web page like Buttons, links, tabs, text bars.

  • We have to create page object class for every page present in the application if the application is a single page application (spa) we have to create page object classes for each tab.
  • Page Object Model class contains 3 components.
    • Web element present on webpage and declared as private.
    • Page Factory Constructor, it will be helpful to initialize the web elements present in the class
    • Methods, which are used to access the webelement declared in the page object class.

In this tutorial, we are going to create a simple framework for google page with Selenium Webdriver.

Reading QR Code from the website using Webdriver

Page Object Class

Page Object class contains all the page object(web elements) for a particular page. For every page present in the application, we have to write the Page Object class.

Page Object class name should end with PO so that it will be easy for the user to identify the class.

Steps to Create :

  • Create a Java project in eclipse and add all selenium webdriver jars
  • Create a package called po some people also prefer objectrepository without space
  • Create a Class called GooglePO, which is Page Object Class. This class will store all the web elements present in the Google Page
  • Once we have created the PO class, we have to add web elements to the class.

Different ways to create Page Object (Web element in PO class):
1. @FindBy :

@FindBy helps selenium testers to find the element on the webpage; to declare elements in PO class, we can use @FindBy with the following syntax.

@FindBy(locator = "locator value")
public WebElement elementName;

// method 1 using FindBy
@FindBy(name="q")
public WebElement searchBar;
public GooglePO(WebDriver driver) {
	PageFactory.initElements(driver, this);
}

The disadvantage with this way is, we cannot use varying value at the place of locator value; it always should be constant String.

Xpath in Selenium

2. Static Method way

We can create methods for the web elements using java static methods, which return web elements; static method way provides us the flexibility to handle varying locators; this method accepts driver as a parameter.

public static WebElement methodName(WebDriver driver){
	return driver.findElement(By.locator(locator value));
}


// method 2 using static method
public static WebElement searchButton(WebDriver driver){
	return driver.findElement(By.xpath("//input[contains(@value,'Search')]"));
}

The disadvantage this way is when the user runs the test cases in parallel, there is a chance to fail because we are using static methods. Only one copy of static methods exists per class.


3. Non-Static method way :

To help multi-threading/ parallel execution, we have to use non-static methods to create page objects, We have to write a constructor in these classes, and the constructor should accept the driver as a parameter. Using this driver, we have to assign a global driver present in the PO class

// method 2 using non static method
public WebElement methodName(){
	return driver.findElement(By.locator(locator value));
}

// method 2 using non static method
public WebElement logoOnSearchResult(){
	return driver.findElement(By.xpath("//h1/a[@id='logo']"));
}


The complete PO class looks like the below program.

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class GooglePO {
	private WebDriver driver;

	// method 1 using FindBy
	@FindBy(name="q")
	public WebElement searchBar;
	public GooglePO(WebDriver driver) {
		// this is for non static method way
		this.driver = driver;
		PageFactory.initElements(driver, this);
	}

	// method 2 using static method
	public static WebElement searchButton(WebDriver driver){
		return driver.findElement(By.xpath("//input[contains(@value,'Search')]"));
	}

	// method 2 using non static method
	public WebElement logoOnSearchResult(){
		return driver.findElement(By.xpath("//h1/a[@id='logo']"));
	}
}


Test class in Page Object Modal :
1. Create packed called test

2. Create a Java Class called GoogleSeachTest

3. Open Firefox browser by setting the geckodriver.exe path to the system variable

// set  gecko driver.exe file path
System.setProperty("webdriver.gecko.driver", "C:/~/geckodriver.exe");
// create object for browser
WebDriver driver = new FirefoxDriver();


4. Navigate to google.com

driver.get("https://google.com");


5. Create an object for GooglePO class, in which we have stored our page object (web elements), pass driver as a parameter

GooglePO gp = new GooglePO(driver);


6. (method 1) With the help of GooglePO class object access the element created by the @FindBy

gp.searchBar.sendKeys("POM test");


7. (method 2) We can access static members using the Class name, access the searchButton using GooglePO class name.

GooglePO.searchButton(driver).click();


8. (method 3) Acces non-static method using GooglePO class object

gp.logoOnSearchResult().click();


The complete program of the Test class looks like below.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import po.GooglePO;

public class GoogleSeachTest {
	public static void main(String[] args) {
		// set  gecko driver.exe file path
		System.setProperty("webdriver.gecko.driver", "C:/~/geckodriver.exe");
		// create object for browser
		WebDriver driver = new FirefoxDriver();
		// navigate to google
		driver.get("https://google.com");

		// create object for GooglePO class
		GooglePO gp = new GooglePO(driver);
		// access searchBar page object  from GooglPO PO class
		gp.searchBar.sendKeys("POM test");

		// accessing static method
		GooglePO.searchButton(driver).click();

		// access non static method using object of GooglePO class
		gp.logoOnSearchResult().click();
	}
}

Handling Custom Dropdowns in selenium

Project structure

pom-selenium-webdriver

Capture screenshots for framework in selenium

Page object with Variable

We can also use a variable for writing the page object (web element) in selenium, but the only issue is you cannot customize much in case of variables.

Below example only to showcase that we can also use a variable for page object but do not use it in the framework.

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class POWithVariable {
	WebDriver driver;
	public POWithVariable(WebDriver driver) {
		this.driver = driver;
	}
	// variable as page objects
	public WebElement searchBar =  driver.findElement(By.name("q"));
	public WebElement searchButton =  driver.findElement(By.xpath("//input[contains(@value,'Search')]"));
	public WebElement logo =  driver.findElement(By.xpath("//h1/a[@id='logo']"));
}

this.driver = driver;

We have used this.driver = driver; code a couple of times on this page, but what does that mean.

this keyword points the object of the class created by the constructor, as this global driver Webdriver driver; is not initialized.

We want to initialize 'global level driver' value with the help of the user, so we accept driver value in the constructor with a parameter of driver, and we set 'constructor level driver' value to the 'global level driver', so that we can use the 'global level driver' in all the methods or where ever required.

In the next tutorial, we will learn the fully-featured Page Object Model Framework


Hybrid Inheritance in Java and Selenium

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions