POM Architecture in Selenium


This article will cover:

1. Introduction to POM design pattern
2. Structure of a page class in POM design pattern
3. Structure of a test class in POM design pattern
4. Handling page navigation in Page Object Model design pattern
5. Create independent Test Case in POM design pattern
6. Execution flow







What is Page Object Model design pattern ?


The page object model is a design pattern where every page is treated as an object and every page has a corresponding test class to test the page's functionalities. Here page is an encapsulation of page elements and operations to be performed on the page. The objective of POM is to separate out the test functions, validation, and assertions from the page to increase the code reusability, maintainability, and readability. If any changes happen on the page's layout, or functionality, then only that particular page object has to be updated and not the entire suite.

In the POM design pattern, we are treating every page as an object and these objects are used in the corresponding test class to perform the operations on the page and validate the result.

For every web page, we create a java/class file for e.g. there will be a java file for the 'Login' page, a separate java file for the 'Home' page, a separate java file for the 'About Us' page, and so on. Every page has a corresponding test class. A typical POM structure can be seen in the below image.

folder structure in page object model



Structure of a page class in POM design pattern


Create a java class corresponding to a page and inside the class - declare the page elements, initialize the page elements upon its object creation, and define the methods for performing operations on the page.

The page class in POM design pattern has three main components:

1. Declaration of page elements.
2. Initialization of page elements locators.
3. Defining the operations to be performed on the page.

In the page class, we declare the locators of the page elements present on that page as a "By" class object. The locator initialization code is written in the constructor of the page class and these locator elements will be initialized during the object creation of the page class. Below image depicts the declaration of locators of page elements.

declaring page elements in a class

The locators of the Home page gets initialized when an object of home page is created.

initializing the locators



Lastly, the actions or operations to be performed on the page will be defined in the page class as page functions or page methods. For e.g. The "home" page has the username and password fields along with the role selection and submit button. So entering the user name can be considered as one operation, entering the password can be considered as another operation, and selecting the role and clicking the submit button can be considered other operations that are to be performed on the home page.
Below are the page methods depicting the operations to be performed on the home page.

defining operation in page class


Structure of a test class in POM design pattern


Create a test class corresponding to a page object/class and inside the class - define the preconditions which are to be executed before the test execution begins, define the test methods and assertions, and lastly define the post-conditions which are to be executed after the test execution completes.

As we have already seen that every page class has its corresponding test class. The operations defined in the page class will be called through its corresponding test class. A test class in POM design pattern has the following components:

1. Preconditions
2. Test methods/ (Test cases)
3. Postconditions


structure of a test class

Preconditions: All the operations which are to be performed before the test case execution begin should be part of preconditions. The method with "@BeforeMethod" annotation takes care of all the preconditions.

Test methods are the ones in which operations on the page will be performed by calling the page methods and assertions are applied to validate whether the actual result is matching with the expected one or not. In the below example, "clicksubmenu()" is a test method which is calling the method of the home page and asserting whether the user is navigated to a submenu or not.

test method

Postconditions are the ones that are to be executed after the completion of the test method like quitting the driver, releasing the resources, etc.

So in the page class, we define the function, and in the test file, we call those functions. In this way, we separate out the test execution from the pages.





Handling page navigation in Page Object Model design pattern


The implementation of page navigation in POM design pattern is as follows:
(The same is covered in detail in our article on page navigation in POM).
The method resulting in the navigation to another page should return the object of the landing page. This will initialize the page element locators and web driver of the landing page. For .e.g. if on the home page if clicking the 'About Us' link is redirecting to the 'About Us' page then the click operation to the "about us" link should return the object of the "about us" class. The method written in homepage.java should be like this-

public aboutUsPage clickonAboutUsLink()
{
Webdriver code;
return new aboutUsPage(webdriver);
}



Below is the real-time code snippet for handling the page navigation in the POM design pattern. Clicking on the product present on the home page is resulting in the navigation to the "submenu" page. Therefore the "clicking on product" operation is returning the submenu page object and thereby causing the initialization of sub-menu page elements locators along with the submenu page web driver.

operation resulting in navigation to other page returning object of that page

This way, the constructor of resulting page gets triggered and page elements and webdriver of subMenuPage gets initialized.





Create independent Test Case in POM design pattern


In an application under test, the end-to-end business flow has series of dependent test cases that must be executed in sequence. Consider a scenario of the online shopping site Flipkart in which we want to validate the addition of products in the cart. Below will be the sequence of events:

1. Launch the application
2. Log in to the application and visit the home page
3. Click a product on the home page and navigate to the sub-menu page
4. Now click a product on the sub-menu page and navigate to the product detail page
5. Click add to cart button


Here step 3 and step 4 are separate test cases but are also the preconditions for the fifth test case because without reaching the product detail page, we cannot add items to the cart. Therefore, in order to execute the "add to cart" test case in isolation or independently, add its dependent test cases in the precondition of the "add to cart" test case.

previous test cases in precondition

Execution order:

1. Here "clicking the product" operation at the home page results in navigating the user to the sub-menu page therefore this method returned the object of the sub-menu page class. At this point, the page elements and driver of the submenu page get initialized.

2. Now click the product on the sub-menu page, this action will navigate the user to the product detail page and therefore object of product detail page class is returned.

3. Till now we have executed 2 cases in the precondition for "add to cart" and get the product detail page object. The page elements and driver of the "product detail" page get initialized. This "product detail" page object will be used to call the "add to cart" in the test method.





Execution flow of page object model


When we execute our testng.xml file where our test classes are mapped (please refer: http://techno-geeks.co.in/testNG.html to see the structure of testng.xml file), the testng.xml triggers the respective test class defined in it. This test class creates an object of its respective page class and call methods or operations defined under the page class. Once the object of a page class is created, its constructor gets called and all the web components and web driver belonging to that page get initialized. Whenever such an operation is called from the test class which results in navigation to another page, another page's constructor gets called and web components and web driver belonging to the resulting page gets initialized. In this way a typical page object model design pattern works.