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. [转] JS nodeType返回类型

    将HTML DOM中几个容易常用的属性做下记录: nodeName.nodeValue 以及 nodeType 包含有关于节点的信息. nodeName 属性含有某个节点的名称. 元素节点的 node ...

  2. yii cgridview 如何显示图片

    发布的新闻或介绍里有图片,图片存的是Url地址,通过yii的cgridview,默认是数据库里存的啥就显示啥,如何把url地址转为图片?直接上代码 <?php $data = $model-&g ...

  3. Resizing LVM Logical Volumes-lvextend

    1. fdisk命令/dev/sdc再分出一个sdc2分区 [root@rhel7 ~]# fdisk /dev/sdc Welcome to fdisk (util-linux ). Changes ...

  4. fastUtils学习

    比传统java集合工具类速度更快 google的guava也新增了java容器新的功能,功能更加强大,参考文档:http://www.ibm.com/developerworks/cn/java/j- ...

  5. linux的sudo apt-get install 和dpkg -i <package.deb>命令

    ubuntu统一的安装软件命令 sudo apt-get install ** sudo dpkg -i <package.deb>

  6. Shell中IFS用法

    一 .IFS的介绍    Shell 脚本中有个变量叫IFS(Internal Field Seprator) ,内部域分隔符.完整定义是The shell uses the value stored ...

  7. 系统管理中 bash shell 脚本常用方法总结

    在日常系统管理工作中,需要编写脚本来完成特定的功能,编写shell脚本是一个基本功了!在编写的过程中,掌握一些常用的技巧和语法就可以完成大部分功能了,也就是2/8原则 1. 单引号和双引号的区别 单引 ...

  8. Nagios设置只监控不报警

    设置全部监控项都开启邮件报警: vim /usr/local/nagios/etc/nagios.cfg 设置 enable_notifications=1    1为开启,0为关闭     如个别监 ...

  9. wsdl和wadl区别

    [转]http://blog.csdn.net/liuxiao723846/article/details/51611183 1.Java开发WebService最重要的两个规范: JSR-224 ( ...

  10. 关于<%@ include file=" " %>与<jsp:include page=""></jsp:include>中的那些问题?

    今天在使用<%@ include file=" " %>指令时,竟然在页面中不让使用?这是怎么回事:问题如下图: 顿时被这个问题给搞到了!!!突然想到在以前的 JSP ...