Base Class In Page Object Model | Part 3

Base Class In Page Object Model

 

In Part 1 and Part 2 of this tutorial series, we learn how to:

  • create the basic framework structure for the page object model approach.
  • separate the business logic with the test scripts.
  • handle page navigation (using return statements). Page object model approach is also known as page chaining.

In this tutorial, we will learn what is a base class in page object model and how to refactor the code. We will be doing more code refactoring as we move towards the page factory concept.

The page object model is solely based on the pages (web page) and the actions (methods) that can be performed on the page. In the last tutorial, there was repeated use of WebDriver object in the page classes. We initialized the WebDriver object for each page class inside the respective constructor.

Below is the diagrammatic representation of the page classes and the test class:

 

Page Object Model tutorial

 

Above diagram clearly represents the redundancy in the current implementation. In every class:

  • WebDriver object is declared
  • WebDriver object is initialized in the respective constructor
  • The ChromeDriver path is defined in the test class
  • Navigating to the application URL.

To remove the above redundancies, the concept of base class in page object model is introduced. This concept utilizes the java inheritance OOP property. All the repetitive code is moved to a class, which acts as a parent class for all other classes. This parent class is also known as the base class.

 

Create a base class in page object model

 

Once all the dependent logic is identified, the next step is to move all the related code to the base class. In package com.appliedselenium.pages create a new class BasePage.java and paste the following code:

 

package com.appliedselenium.pages;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class BasePage {
    
    
    //Declare the WebDriver
    public static WebDriver driver;
    
    
    //constructor of base class
    public BasePage() {
        
        if (driver == null) {
    //Set the path for chromedriver
            String filePath = System.getProperty("user.dir");

            System.setProperty("webdriver.chrome.driver", filePath + "/src/test/resources/com/appliedselenium/drivers/chromedriver");
            
            driver     = new ChromeDriver();
            
            //go to application
            driver.get("http://automationpractice.com/index.php");
            driver.manage().window().maximize();
        }
            
    }
    

}

 

public static WebDriver driver – here the WebDriver object is declared as static to hold the last WebDriver reference. This line ensures that the driver should always retain the latest reference.

if (driver == null) – this statement will be true for the first test. Subsequent driver instances would not be null (because of the above used static keyword). If we remove this line, a new browser window would open for each page.

Rest of this class code is copied from the LandingPageTest.java class. Below is the updated LandingPageTest.java class:

 

package com.appliedselenium.tests;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import com.appliedselenium.pages.BasePage;
import com.appliedselenium.pages.HomePage;
import com.appliedselenium.pages.LandingPage;
import com.appliedselenium.pages.ProductSearchPage;
import com.appliedselenium.pages.SignInPage;

public class LandingPageTest {

    public static void main(String[] args) throws Exception {

        //Declare an object of class ProductSearchPage class
        ProductSearchPage pr;
        SignInPage inPage;
        HomePage homePage;

        
        //Instantiate LandingPage class object
        LandingPage landingPage = new LandingPage();
        
        //Verify the titles
                if(landingPage.getTitle().equals("My Store")) {
                    System.out.println("Title Matched - Test Passes");
                }else {
                    System.out.println("Title doesn't match - Test Failed");
                }

        
        //Navigate to Product Search page
        landingPage.searchProduct();
        
        //Instantiate ProductSearchPage class object
        pr = new ProductSearchPage();
        
        //Verify the text
        if(pr.getProductSearchResult().contains("Printed Summer Dress")) {
            System.out.println("Product Found");
        }else {
            System.out.println("Product Search Failed");
        }

        
    
        //Click on Sign In button
        landingPage.clickOnSignIn();
        
        inPage = new SignInPage();
        inPage.userSignIn("abc11001@xyz.com", "abcxyz");
        
        homePage = new HomePage();

        
        if(homePage.verifyCorrectLogin().equals("abc xyz")) {
            System.out.println("Login Successful");
        }else {
            System.out.println("Login Failed");
        }
        
        
    }

}

 

 

Update child classes

 

Below is the updated code for rest of the page classes:

 

package com.appliedselenium.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LandingPage extends BasePage{
    
    

    
    //First Test. This title should be verified in LandingPageTest class
    public String getTitle() {
        return driver.getTitle();
    }
    
    
    //Searching for a product at landing page returns (displays) product search page. Hence 
    //the return type is ProductSearchPage and return value is new ProductSearchPage() 
    public ProductSearchPage searchProduct() {
        
        //Enter text dress in the search text box
        driver.findElement(By.id("search_query_top")).sendKeys("dress");
        
        //Click on Search button
        driver.findElement(By.name("submit_search")).click();
        
        //Product search page is displayed
        return new ProductSearchPage();
        
    }
    
    //Click on Sign In button
    public SignInPage clickOnSignIn() {
        
        driver.findElement(By.xpath("//a[@class='login']")).click();
        
        //clicking on Sign In button will display Sign In page
        return new SignInPage();
    }
    

}

                       LandingPage.java

 

 

package com.appliedselenium.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class ProductSearchPage extends BasePage{

    
    
    //method to return the product text
    public String getProductSearchResult() {
        
        String result = driver.findElement(By.xpath("//div[@class='right-block']//a[@class='product-name']")).getText();
        return result;
    }

}

                    ProductSearchPage.java

 

 

package com.appliedselenium.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class SignInPage extends BasePage {


    
    public HomePage userSignIn(String email, String password) {
        
        driver.findElement(By.id("email")).sendKeys(email);
        driver.findElement(By.id("passwd")).sendKeys(password);
        driver.findElement(By.id("SubmitLogin")).click();
        
        return new HomePage();
        
    }

}

                   SignInPage.java

 

 

package com.appliedselenium.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class HomePage extends BasePage{
    

    
    public String verifyCorrectLogin() {
        
        String text = driver.findElement(By.xpath("//a[@class='account']/span")).getText();
        return text;
    }

}

                        HomePage.java

 

Changes in the page classes are highlighted in bold. There are only 2 changes:

  • extends keyword is added to every page class. This is the concept of inheritance in java. This allows the WebDriver object to be available to all the page classes, as it is available in BasePage.java class.
  • driver variable is removed (as a parameter) while returning the page class references.

Also, the LandingPageTest.java test class is completely refactored and independent of driver variable.

There is more to the base class in page object model, which we will see in the next tutorial. Your code should run without any error for the future tutorials. Comment below if you need any help.

Author: Dhawal Joshi

A post-graduate in MCA, ISTQB & ITIL certified QA with more than 8 years of experience in QA working with a CMMI Level 5 organization as System Analyst. I started my automation journey with HP UFT(formerly known as QTP) and for the past few years, I am using Selenium for automation. I also have experience in Android Application Development, Java, HTML, and VBScript. When I am not working, I like to spend time with my family, cooking and learning new developments in IT.

7 thoughts on “Base Class In Page Object Model | Part 3

  1. Hi,
    Nice Explanation . I do have a question, i am developing a hybrid framework. Suppose 20 pages are there in my application, it should get logged in 20 times for each page or should logged in once and execute allother pages one after another.

    1. This depends on the nature of your tests. If your tests/test suite requires you to close the browser, then you must close the browser and re-login. Some of these instances are:
      1. Banking website – it forces the user to close the browser window after logout.
      2. Role-based testing where you are required to logout and login with a different user, etc.

      If your complete test flow does not require logout for each page, then no need to logout and login. Read carefully the manual test case and identify if you need to sign in for all the pages all the time.

      Happy Learning 🙂

  2. Thanks for your reply. For me challenge is i have to do automation testing without manual test cases.
    In my application 10 modules are there and when we mouse hover on each of it, give 4-5 more options/pages. I am developing a hybrid framework using POM pattern, Maven,extent report.
    When running TestNg suite its also running successfully and generating report. Should i execute individual module? Say I have one module Edit User — Having for options/pages Like Edit User Profile, Change Password, About, Logout. Same way each module have number of options. Please give me some more idea how do i create structure or how do i execute.

    1. Purvi you’ll get all these solutions if you go through the entire article. Primarily, you should create a separate page class for each page. Then there would be some elements that are common across the application, the page objects for these web elements should be put in a separate class and make that class static.

      Also, you must know the functionality of the application. This will help you in identifying the application workflow (for eg which page is displayed after an action happens on any web element of current web page), this is also known as page chaining.

      Suppose you have 3 pages A, B and C for which you have created 3 java pages classes APage, BPage and CPage. Assume that there is a link (or the element which is displayed on mouse hover in your case) on APage which upon clicking redirects to page B (in java terms clicking the link on page A returns the object of BPage class, this is very well explained in this tutorial series). Then APage class should contain object of class BPage only and CPage class is not at all in picture.

      In your case, start creating the different page classes and group them in different packages according to their functionality. Refer THIS PART of the tutorial series.

  3. I really appreciate, your detailed reply to my question.

    It has cleared some of my doubts and yes as per your suggestion, i have gone through entire article but still i am some where confuse because lack of my subject knowledge. But yes very good explanation.

    I do have a question, better i ask on related article(part-8).

Leave a Reply

Your e-mail address will not be published. Required fields are marked *