Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide

 

Before we learn about Page Object Model, lets understand -

Why POM ?

Starting a UI Automation in Selenium WebDriver is NOT a tough task. You just need to find elements, perform operations on it .

Consider this simple script to login into a website

As you can observe, all we are doing is finding elements and filling values for those elements.

This is a small script. Script maintenance looks easy. But with time test suite will grow. As you add more and more lines to your code, things become tough.

The chief problem with script maintenance is that if 10 different scripts are using the same page element, with any change in that element, you need to change all 10 scripts. This is time consuming and error prone.

A better approach to script maintenance is to create a separate class file which would find web elements , fill them or verify them. This class can be reused in all the scripts using that element. In future if there is change in the web element , we need to make change in just 1 class file and not 10 different scripts.

This approach is called Page Object Model(POM). It helps make code more readable, maintainable, and reusable.

What is POM?

  • Page Object Model is a design pattern to create Object Repository for web UI elements.
  • Under this model, for each web page in the application there should be corresponding page class.
  • This Page class will find the WebElements of that web page and also contains Page methods which perform operations on those WebElements.
  • Name of these methods should be given as per the task they are performing i.e., if a loader is waiting for payment gateway to be appear, POM method name can be waitForPaymentScreenDisplay().

Advantages of POM

  1. Page Object Patten says operations and flows in the UI should be separated from verification. This concept makes our code cleaner and easy to understand.
  2. Second benefit is the object repository is independent of testcases, so we can use the same object repository for a different purpose with different tools. For example, we can integrate POM with TestNG/JUnit for functional testing and at the same time with JBehave/Cucumber for acceptance testing.
  3. Code becomes less and optimized because of the reusable page methods in the POM classes.
  4. Methods get more realistic names which can be easily mapped with the operation happening in UI. i.e. if after clicking on the button we land on the home page, the method name will be like 'gotoHomePage()'.

How to implement POM ?

Simple POM:

It's the basic structure of Page object model (POM) where all Web Elements of the AUT and the method that operate on these Web Elements are maintained inside a class file. Task like verification should be separate as part of Test methods.

Complete Example

TestCase: Go to Guru99 Demo Site .

Step 1) Go to Guru99 Demo Site
Step 2) In home page check text "Guru99 Bank" is present
Step 3) Login into application
Step 4) Verify that the Home page contains text as "Manger Id : demo"

Here are we are dealing with 2 pages

  1. Login Page
  2. Home Page (shown once you login)

Accordingly we create 2 POM classes

Guru99 Login page POM

package pages;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99Login {

    WebDriver driver;

    By user99GuruName = By.name("uid");

    By password99Guru = By.name("password");

    By titleText =By.className("barone");

    By login = By.name("btnLogin");

    public Guru99Login(WebDriver driver){

        this.driver = driver;

    }

    //Set user name in textbox

    public void setUserName(String strUserName){

        driver.findElement(user99GuruName).sendKeys(strUserName);;

    }

    //Set password in password textbox

    public void setPassword(String strPassword){

         driver.findElement(password99Guru).sendKeys(strPassword);

    }

    //Click on login button

    public void clickLogin(){

            driver.findElement(login).click();

    }

    //Get the title of Login Page

    public String getLoginTitle(){

     return    driver.findElement(titleText).getText();

    }

    /**

     * This POM method will be exposed in test case to login in the application

     * @param strUserName

     * @param strPasword

     * @return

     */

    public void loginToGuru99(String strUserName,String strPasword){

        //Fill user name

        this.setUserName(strUserName);

        //Fill password

        this.setPassword(strPasword);

        //Click Login button

        this.clickLogin();        

    }

}

Guru99 Home Page POM

package pages;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99HomePage {

    WebDriver driver;

    By homePageUserName = By.xpath("//table//tr[@class='heading3']");

    public Guru99HomePage(WebDriver driver){

        this.driver = driver;

    }

    //Get the User name from Home Page

        public String getHomePageDashboardUserName(){

         return    driver.findElement(homePageUserName).getText();

        }

}

Guru99 Simple POM Test case

package test;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.testng.Assert;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import pages.Guru99HomePage;

import pages.Guru99Login;

public class Test99GuruLogin {

    WebDriver driver;

    Guru99Login objLogin;

    Guru99HomePage objHomePage;

    @BeforeTest

    public void setup(){

        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        driver.get("http://demo.guru99.com/V4/");

    }

    /**

     * This test case will login in http://demo.guru99.com/V4/

     * Verify login page title as guru99 bank

     * Login to application

     * Verify the home page using Dashboard message

     */

    @Test(priority=0)

    public void test_Home_Page_Appear_Correct(){

        //Create Login Page object

    objLogin = new Guru99Login(driver);

    //Verify login page title

    String loginPageTitle = objLogin.getLoginTitle();

    Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank"));

    //login to application

    objLogin.loginToGuru99("mgr123", "mgr!23");

    // go the next page

    objHomePage = new Guru99HomePage(driver);

    //Verify home page

    Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123"));

    }

What is Page Factory?

Page Factory is an inbuilt page object model concept for Selenium WebDriver but it is very optimized.

Here as well we follow the concept of separation of Page Object repository and Test methods. Additionally with the help of PageFactory class we use annotations @FindBy to find WebElement. We use initElements method to initialize web elements

@FindBy can accept tagName, partialLinkText, name, linkText, id, css, className, xpath as attributes.

Let's look at the same example as above using Page Factory

Guru99 Login page with Page Factory

package PageFactory;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.FindBy;

import org.openqa.selenium.support.PageFactory;

public class Guru99Login {

    /**

     * All WebElements are identified by @FindBy annotation

     */

    WebDriver driver;

    @FindBy(name="uid")

    WebElement user99GuruName;

    @FindBy(name="password")

    WebElement password99Guru;

    @FindBy(className="barone")

    WebElement titleText;

    @FindBy(name="btnLogin")

    WebElement login;

    public Guru99Login(WebDriver driver){

        this.driver = driver;

        //This initElements method will create all WebElements

        PageFactory.initElements(driver, this);

    }

    //Set user name in textbox

    public void setUserName(String strUserName){

        user99GuruName.sendKeys(strUserName);

    }

    //Set password in password textbox

    public void setPassword(String strPassword){

    password99Guru.sendKeys(strPassword);

    }

    //Click on login button

    public void clickLogin(){

            login.click();

    }

    //Get the title of Login Page

    public String getLoginTitle(){

     return    titleText.getText();

    }

    /**

     * This POM method will be exposed in test case to login in the application

     * @param strUserName

     * @param strPasword

     * @return

     */

    public void loginToGuru99(String strUserName,String strPasword){

        //Fill user name

        this.setUserName(strUserName);

        //Fill password

        this.setPassword(strPasword);

        //Click Login button

        this.clickLogin();

    }

}

Guru99 Home Page with Page Factory

package PageFactory;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.FindBy;

import org.openqa.selenium.support.PageFactory;

public class Guru99HomePage {

    WebDriver driver;

    @FindBy(xpath="//table//tr[@class='heading3']")

    WebElement homePageUserName;

    public Guru99HomePage(WebDriver driver){

        this.driver = driver;

        //This initElements method will create all WebElements

        PageFactory.initElements(driver, this);

    }

    //Get the User name from Home Page

        public String getHomePageDashboardUserName(){

         return    homePageUserName.getText();

        }

}

Guru99 TestCase with Page Factory concept

package test;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.testng.Assert;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import PageFactory.Guru99HomePage;

import PageFactory.Guru99Login;

public class Test99GuruLoginWithPageFactory {

    WebDriver driver;

    Guru99Login objLogin;

    Guru99HomePage objHomePage;

    @BeforeTest

    public void setup(){

        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        driver.get("http://demo.guru99.com/V4/");

    }

    /**

     * This test go to http://demo.guru99.com/V4/

     * Verify login page title as guru99 bank

     * Login to application

     * Verify the home page using Dashboard message

     */

    @Test(priority=0)

    public void test_Home_Page_Appear_Correct(){

        //Create Login Page object

    objLogin = new Guru99Login(driver);

    //Verify login page title

    String loginPageTitle = objLogin.getLoginTitle();

    Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank"));

    //login to application

    objLogin.loginToGuru99("mgr123", "mgr!23");

    // go the next page

    objHomePage = new Guru99HomePage(driver);

    //Verify home page

    Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123"));

    }

}

Complete Project Structure will look like the diagram:

AjaxElementLocatorFactory

One of the key advantage of using Page Factory pattern is AjaxElementLocatorFactory Class.

It is working on lazy loading concept, i.e. a timeout for a WebElement will be assigned to the Object page class with the help of AjaxElementLocatorFactory .

Here, when an operation is performed on an element the wait for its visibility starts from that moment only. If the element is not found in the given time interval, test case execution will throw 'NoSuchElementException' exception.

Summary

  1. Page Object Model is an Object repository design pattern in Selenium WebDriver.
  2. POM creates our testing code maintainable, reusable.
  3. Page Factory is an optimized way to create object repository in POM concept.
  4. AjaxElementLocatorFactory is a lazy load concept in Page Factory pattern to identify WebElements only when they are used in any operation.

selenium page object model的更多相关文章

  1. Selenium的PO模式(Page Object Model)[python版]

     Page Object Model 简称POM  普通的测试用例代码: .... #测试用例 def test_login_mail(self): driver = self.driver driv ...

  2. Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)

            研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...

  3. Page Object Model (Selenium, Python)

    时间 2015-06-15 00:11:56  Qxf2 blog 原文  http://qxf2.com/blog/page-object-model-selenium-python/ 主题 Sel ...

  4. Python+Selenium框架设计--- Page Object Model

    POM(Page Object Model):页面对象模型,POM是一种最近几年非常流行的自动化测试模型,或者思想,POM不是一个框架,就是一个解决问题的思想.采用POM的目的,是为了解决前端中UI变 ...

  5. Selenium Page object Pattern usage

    使用Selenium的framework,大家免不了要使用他的page object pattern来开发适合自己的framework,原因很简单,page object 可以将测试的对象抽象成一个个 ...

  6. selenium page object模式

    页面对象模式将测试代码和被测试页面的元素及操作进行分离,以降低页面元素的变化对测试代码的影响.每个被测试的页面都会被定义一个类,类中会定位元素和操作. 如果不使用page object模式,则相同的操 ...

  7. Selenium Page Object(PO)设计模式

    Webdriver UI自动化测试火了好几年了,具体怎么设计自动化测试测试工程,组织测试用例完全凭借着自己的经验和习惯. 最近忽然听说了Page Object(简称PO)火了起来,也有面试的时候被问到 ...

  8. web端自动化——selenium Page Object设计模式

    Page Object设计模式的优点如下: ①    减少代码的重复. ②    提高测试用例的可读性. ③    提高测试用例的可维护性,特别是针对UI频繁变化的项目. 当为Web页面编写测试时,需 ...

  9. Appium+Python之PO模型(Page object Model)

    思考:我们进行自动化测试时,如果把代码都写在一个脚本中,代码的可读性会变差,且后期代码维护也麻烦,最好的想法就是测试对象和测试用例可以分离,可以很快定位问题,代码可读性高,也比较容易理解.这里推荐大家 ...

随机推荐

  1. mysql 创建数据库使用默认字符集(备忘)

    GBK: create database test2 DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci; UTF8: CREATE DATABASE ` ...

  2. REMOTE HOST IDENTIFICATION HAS CHANGED

    今天在使用scp命令上传文件到远端服务器时报如下错误,(ssh命令连接到远程服务器时也报同样的错误): @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...

  3. LINQ Enumerable 续

    筛选序列 Enumerable.Distinct 对于复杂的对象列表,运行时引擎如何才能通过比较确定两个对象是否重复?对于复杂对象,必须提供一个比较器,即实现IEqualityComparer(Of ...

  4. AjaxManager的实现

    在NeralJS思路整理一章中我们提到过实用ajax管理模块控制ajax请求,以减少ajax请求数量,优化加载,以下是ajax模块的实现,我已经确保经历简单. /** * Created by wil ...

  5. 注意mysql中的编码格式和php中的编码格式一致

    今天发现用php代码插入英文可以,但是中文插入不进去,注意编码要一致,@mysql_connect("localhost","root","12345 ...

  6. XFire构建服务端Service的两种方式

    1.原声构建: 2.集成spring构建 http://blog.csdn.net/carefree31441/article/details/4000436XFire构建服务端Service的两种方 ...

  7. Swift中简单的单例设计

    import Foundation class Test: NSObject { // 提供单例实例 static let shareInstance = Test() // 私有化构造方法 over ...

  8. Mysql 视图笔记2

    这学期开了数据库的课,对sql注入颇感兴趣.因此,对数据库语句也颇为喜爱.遇到了with check option 问题.这属于sql view里面的一个问题.在此略做小结.大牛勿喷! 先自定义一个t ...

  9. EcStore操作笔记

    1.去掉首页里面代码: <meta http-equiv="content-type" content="text/html; charset=utf-8" ...

  10. jquery mobile 复选框和单选框

    checkbox 和radio <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g ...