Page Object Model (POM) using Page Factory in Selenium

In last post we have seen Page Object Model with basic approach, in this post we will see Page Object Model using Page Factory in Selenium.

What is PageFactory?
PageFactory Class in Selenium is an extension to the Page Object design pattern. It is used to initialize the web elements of the Page. It is used to initialize elements of a Page class without having to use 'FindElement' or 'FindElements'.

Here we follow the below steps to implement Page Object Model using Page Factory:

POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>POMPageFactory</groupId>
  <artifactId>POMPageFactory</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <dependency>
   <groupId>org.testng</groupId>
   <artifactId>testng</artifactId>
   <version>7.1.0</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-java</artifactId>
   <version>3.141.59</version>
  </dependency>
 </dependencies>
</project>

Steps to be followed to create Base Class
  • Declare web driver as static and Initialize the web driver and open the application using setup method.
  • Create an object of page layer class(Only need to create LoginPage object inside setup method).
  • Close the browser using tearDown method.
  • You can have some other common methods as well which will be used across framework like implicit waits, taking screen shots etc.
BaseClass.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import com.OrangeHRM.pages.LoginPage;

/**
 * @author Hitendra
 *  
 */
public class BaseClass {
 
 public static WebDriver driver;
 public LoginPage loginPage;
 
 @BeforeMethod
 public void setup() {
  System.setProperty("webdriver.chrome.driver",
    "C:\\Users\\Hitendra\\Downloads\\chromedriver_win32 (1)\\chromedriver.exe");
  driver= new ChromeDriver();
  driver.manage().window().maximize();
  driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/validateCredentials");
  loginPage=new LoginPage();
 }
 @AfterMethod
 public void tearDown() {
  driver.close();
 }
}

Steps to be followed to create page classes
  • Create a Java class for every page in the application (This class will extend BaseClass).
  • In each class, declare all the web Elements as variable using @FindBy.
  • Implement corresponding methods acting on the variables.
  • Construct page chaining logic - lets say in LoginPage.java we have login method and when we perform actions like entering username, password and clicking on login button then user lands HomePage. So login method will return object of HomePage.java class.
  • Add constructor to initialize the web elements initElements method.
Page Chaining Model
LoginPage.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

import com.OrangeHRM.base.BaseClass;

public class LoginPage extends BaseClass {
 
 @FindBy(id="txtUsername") 
 WebElement userName;
 
 @FindBy(name="txtPassword") 
 WebElement password;
 
 @FindBy(xpath="//*[@id=\"btnLogin\"]") 
 WebElement loginBtn;
 
 @FindBy(xpath="//*[@id=\"divLogo\"]/img") 
 WebElement logo;
 
 public LoginPage() {
  PageFactory.initElements(driver, this);
 }
 
 public boolean validateLogo() {
  logo.isDisplayed();
  return true;
 }
 //This method will return object of HomePage class as we are landing on 
 //HomePage using this method
 public HomePage login(String uname, String pswd) {
  userName.sendKeys(uname);
  password.sendKeys(pswd);
  loginBtn.click();
  return new HomePage();
 }
}

HomePage.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import com.OrangeHRM.base.BaseClass;

public class HomePage extends BaseClass {
 
 @FindBy(xpath="//*[@id=\"menu_admin_viewAdminModule\"]/b")
 WebElement adminTab;
 
 public HomePage() {
  PageFactory.initElements(driver, this);
 }
 //This method will return object of SystemUsersPage class as we are landing on 
 //SystemUsersPage using this method
 public SystemUsersPage clickOnAdminTab() {
  adminTab.click();
  return new SystemUsersPage();
 }
}

SystemUsersPage.java -  Just created this page class without writing anything inside it.
public class SystemUsersPage {

}

Steps to be followed to create test cases
  • Create test class for every corresponding page class. Like LoginPageTest, HomePageTest etc. (This class will extend BaseClass).
  • Using the object reference, call the method from page layer class.
  • Insert the assert in the test method to validate the scenarios.
  • Repeat step#3 until all actions are performed.
LoginPageTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
import com.OrangeHRM.base.BaseClass;
import com.OrangeHRM.pages.HomePage;

public class LoginPageTest extends BaseClass {
 HomePage homePage;
 
 @Test(priority = 1)
 public void logoTest() {
  boolean flag=loginPage.validateLogo();
  Assert.assertTrue(flag);
 }
 @Test(priority = 2)
 public void loginTest() {
  homePage=loginPage.login("admin", "admin123");
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/dashboard";
  String actualURL=BaseClass.driver.getCurrentUrl();
  Assert.assertEquals(actualURL, expectedURL);
 }
}

HomePageTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
import com.OrangeHRM.base.BaseClass;
import com.OrangeHRM.pages.HomePage;

public class HomePageTest extends BaseClass {
 HomePage homePage;
 
 @Test(priority = 3)
 public void clickOnAdminTab() throws InterruptedException  {
  homePage=loginPage.login("admin", "admin123");
  homePage.clickOnAdminTab();
  Thread.sleep(2000);
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/admin/viewSystemUsers";
  String actualURL=BaseClass.driver.getCurrentUrl();
  Assert.assertEquals(actualURL, expectedURL);
 }
}

testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test thread-count="5" name="Test">
    <classes>
      <class name="com.OrangeHRM.testcases.LoginPageTest"/>
      <class name="com.OrangeHRM.testcases.HomePageTest"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

YouTube video will be coming soon...

1 comment: