In this post, we’ll present a step-by-step tutorial on the page object model in Selenium which is a standard design pattern for solving real-time problems.
In the world of test automation, Selenium RC and WebDriver were the de facto web UI automation tools for testers. These tools are open source and available for free use. Many QA engineers aspire to create their private keyword and data-driven test suites using these tools.
Nowadays, the page object model is a new test automation buzzword. It was brought to address the multiple bottlenecks that exist in the old tools. Let’s now move to know more about the page object model.
1- Introduction to Page Object Model (POM)
1.1- Why Page Object Model?
There have been several problems with the traditional automation methods (as referred to above).
1- The most common is script maintenance which gets tougher with time as the test suite grows.
2- Next, when some locator changes, we need to go over the whole source code to adjust locators.
3- Another problem is the duplicate code which arises due to the lack of reusability in the old code.
4- The latter also leads to the duplicity of locators which makes the test code inefficient.
5- Finally, the unnecessary code increases the cost of maintenance for the entire project.
As said in the beginning, the Page Object Model is a design pattern that addresses all of the above issues. It allows easy test case maintenance and reduces duplicate code. It is becoming the most widely used UI automation concept across the Selenium community.
Another aspect of using the Page Object Model is that the big IT companies are asking questions about it during testing job interviews. So we would suggest to all budding test engineers that they should first read this tutorial. And then refer our one of the most popular posts providing 100+ Selenium Interview Questions.
In case you plan to prepare for a Selenium online skill test, then first try the Selenium WebDriver Quiz on our site to gain confidence. Both these posts receive interest from hundreds of visitors on a daily basis. In today’s post, we’ll help you learn the page object model with a full-blown example.
1.2- What is the Page Object Model (POM)?
1- Page Object Model is a design pattern to define container classes for web elements that behave as object repositories.
2- In this model, each page has its private page object class to access UI locators.
3- The Page class maps all elements of the corresponding web page as its private members. Also, it defines public methods to manage operations on these objects.
4- To increase readability – it allows the method name to be set as per the task they are performing. For example, we can use a method name like waitForLoginSuccess() which waits until it gets a success message for the login operation.
1.3- Advantages of Page Object Model
1- You can segregate the UI operations from functional flows. This makes the code clean and easy to manage.
2- It lets the test cases be written independently of the object repository. So the same object repository can be re-used for a different purpose. For example, you can use the POM-based repository for functional testing with TestNG/JUnit and for acceptance testing with JBehave/Cucumber.
3- Here, we have reusable page methods in the POM classes so that you can focus on code optimization.
4- You can use more sensible method names which can be easily mapped to the UI actions. For example, if you click the login button and move to the dashboard page. Then you can give the method name as ‘gotoDashboard()’.
2- How to Implement the Page Object Model?
2.1- The Use Case for the Page Object Model Application
We’ll give you a live example of a page object model class to automate the test cases. Following is a brief summary of the use case.
1- For the demo, we’ll use a test site that is openly available for selenium testing. You can select a Selenium demo site from our blog.
2- The above URL has a landing home page that lists the links for chapters ranging from 1 to 8.
3- By clicking the chapter links, you can navigate to other pages.
4- In this demo, we’ll automate a basic function workflow.
7- We’ll be using the homepage and chapter 1-2 links to create the page objects and the test case class files.
2.2- Steps for Building the Page Object Model Application
1- In the first step, we’ll create Java files for the corresponding pages to hold element locators and their methods.
1.1- HomePage.java
1.2- ChapterFirstPage.java
1.3- ChapterSecondPage.java
2- Secondly, we’ll define a base test case class to define our test case scenario.
2.1- TestBase.java
3- Finally, we’ll prepare a test case class to implement the basic workflow. This class will import the base test class and extend its functionality.
3.1- MyTest.java
3-Page Object Model: A Step-by-Step Example
STEP-(1.1)
package com.techbeamers.page; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class HomePage { private WebDriver driver; @FindBy(linkText = "Chapter1") WebElement chapter1; @FindBy(linkText = "Chapter2") WebElement chapter2; @FindBy(linkText = "Chapter3") WebElement chapter3; public HomePage(WebDriver driver) { this.driver = driver; } // Method-1. public ChapterFirstPage clickChapterFirst() { chapter1.click(); return PageFactory.initElements(driver, ChapterFirstPage.class); } // Method-2. public ChapterSecondPage clickChapterSecond() { chapter2.click(); return PageFactory.initElements(driver, ChapterSecondPage.class); } // Method-3. public void clickChapterThird() { chapter3.click(); } }
STEP-(1.2)
package com.techbeamers.page; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.Select; public class ChapterFirstPage { private WebDriver driver; @FindBy(id = "secondajaxbutton") WebElement secondajax; @FindBy(xpath = "//select[@id='selecttype']") WebElement dropdown; @FindBy(id = "verifybutton") WebElement verifybutton; public ChapterFirstPage(WebDriver driver) { this.driver = driver; } // Method-1. public ChapterFirstPage clickSecondAjaxButton() { secondajax.click(); return PageFactory.initElements(driver, ChapterFirstPage.class); } // Method-2. public ChapterFirstPage clickSecondAjaxButton1(String data1) { System.out.println(data1); return PageFactory.initElements(driver, ChapterFirstPage.class); } // Method-3. public ChapterFirstPage selectDropDown(String value) { new Select(dropdown).selectByVisibleText(value); return PageFactory.initElements(driver, ChapterFirstPage.class); } // Method-4. public ChapterFirstPage verifyButton() { verifybutton.click(); return PageFactory.initElements(driver, ChapterFirstPage.class); } }
STEP-(1.3)
package com.techbeamers.page; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class ChapterSecondPage { private WebDriver driver; @FindBy(xpath = "//input[@name='but2']") WebElement but2; @FindBy(xpath = "//input[@id='random']") WebElement random; @FindBy(linkText = "Index") WebElement index; public ChapterSecondPage(WebDriver driver) { this.driver = driver; } // Method-1. public ChapterSecondPage clickRandom() { random.click(); return PageFactory.initElements(driver, ChapterSecondPage.class); } // Method-2. public ChapterSecondPage clickbut2() { but2.click(); return PageFactory.initElements(driver, ChapterSecondPage.class); } // Method-3. public HomePage clickIndex() { index.click(); return PageFactory.initElements(driver, HomePage.class); } // Method-4. public String getTest() { return index.getText(); } }
From the above code snippets, you can easily understand that element locators are declared using @FindBy annotation. Corresponding methods are also defined to separate them from each other.
The PageFactory class is used to create a run-time object of page classes like:
PageFactory.initElements(driver, HomePage.class);
Another important point here is that whenever any page object method results in a new page navigation, then it should return the object of the new page class. For example, when we click the <Index> link available on the <Chapter2> page, the corresponding method i.e. <clickIndex()> should return the <HomePage> object.
PageFactory.initElements(driver, HomePage.class);
Similarly in another example, when you click on <clickbut2()> then the same page object will return.
PageFactory.initElements(driver, ChapterSecondPage.class);
3.2- STEP-(2)
After creating the desired page object files, we’ll create the base class of the test scripts. Here, you can place the common functions related to the test cases. We’ve named this file as <TestBase.java>.
package com.techbeamers.util; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import com.techbeamers.page.ChapterFirstPage; import com.techbeamers.page.ChapterSecondPage; import com.techbeamers.page.HomePage; public class TestBase { protected WebDriver driver; protected String baseUrl; protected HomePage homePage; protected ChapterSecondPage chapterSecond; protected ChapterFirstPage chapterFirstPage; // Method-1. @BeforeSuite public void setUp() { baseUrl = "http://book.theautomatedtester.co.uk/"; driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); } // Method-2. @AfterSuite public void tearDown() throws Exception { driver.quit(); } }
3.3- STEP-(3)
In the last step, we’ll learn to prepare the test script by importing the TestBase class created in the previous step. Next, you’ll have to call the corresponding methods of the page objects as would be needed to automate the basic test case workflow. The test script’s code is chipped in below so that you can save it as the <MyTest.java> file.
package com.techbeamers.scripts; import org.openqa.selenium.support.PageFactory; import org.testng.Assert; import org.testng.annotations.Test; import com.techbeamers.page.HomePage; import com.techbeamers.util.TestBase; public class MyTest extends TestBase { // Test-0. @Test public void testPageObject() throws Exception { homePage = PageFactory.initElements(driver, HomePage.class); driver.get(baseUrl); chapterSecond = homePage.clickChapterSecond(); chapterSecond.clickbut2(); chapterSecond.clickRandom(); String data = chapterSecond.getTest(); homePage = chapterSecond.clickIndex(); chapterFirstPage = homePage.clickChapterFirst(); chapterFirstPage.clickSecondAjaxButton(); chapterFirstPage.clickSecondAjaxButton1(data); chapterFirstPage.selectDropDown("Selenium Core"); chapterFirstPage.verifyButton(); } }
Footnote – Implementing the Page Object Model
Hello, dear readers, we hope the above explanation of the Page Object Model has given you a fair idea about the topic. And now you should be able to use it in your working environments.
You must know that this is not an end to the knowledge and application of Selenium technology. There is much more to read and understand for each one of us. So, we’ll keep coming up with new things and concepts in the time to come.
Before we leave you here, we request you to share your feedback in the comment section. You can also support us by distributing this post in your friend circle and spreading awareness about the Page Object Model.
All the Best,
TechBeamers.