Page Object Model | Framework Design – Part 2

Page Object Model Framework

 

In our previous article, we have created a maven project and in this tutorial, we will add more components to it. This Page Object Model tutorial is without Page Factory. In the upcoming tutorial, we will learn how to implement page object model using the page factory.

Before starting with the framework design, consider the application flow with regards to the test cases mentioned in the previous tutorial.

  1. Is the landing page displayed?
    • The landing page is the default page.
  2. Verify if the user is able to search for a particular product?
    • Landing Page – > Input text in the search text box, hit enter -> Product Search Page
  3. Validate if the user is able to sign in successfully?
    • Landing Page -> Sign In Page (after clicking Sign In link at landing page) -> Home page after successful login.

 

Page Object Model – Components

 

Maven project comes with its own structure. We will utilize the structure as follows. Keep in mind that we are not using the page factory concept yet, hence things will change in upcoming tutorials:

src/main/java – This folder should contain all the business logic, or in simple words, it should contain the page classes.  The page classes should contain the methods to interact with the web elements present in it. Create a package com.appliedselenium.pages in this folder.

src/test/java – This folder contains actual test scripts. You may also include the database utilities, listeners, etc. to this folder. Create the following packages inside this folder:

  • com.appliedselenium.tests
  • com.appliedselenium.utils
  • com.appliedselenium.listeners

src/test/resources – This folder contains the common utilities and test data. Create the following packages inside this folder:

  • com.appliedselenium.exceldata
  • com.appliedselenium.drivers
  • com.appliedselenium.logs
  • com.appliedselenium.properties
  • com.appliedselenium.testng

We will look into the contents of these folders shortly. Your eclipse folder structure should now look as below:

 

Page Object Model Framework

 

 

Update POM.xml

 

The pom.xml gives us control over different versions of the libraries/jars we are going to use in our framework. We will not download any selenium or extent report jar file, rather we will add their dependency in this pom.xml file between <dependency> and </dependency> under <dependencies> and
</dependencies> tags.

If you are not aware of the dependency, just remember they are the version of the jar or library which we have to put in our pom.xml file. To find any dependency, just google the library name with “maven dependency” added.

Copy and paste below code to your pom.xml file.

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.appliedselenium</groupId>
    <artifactId>PageObjectNoPageFactory</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>4.0.9</version>
        </dependency>
        

        <!-- https://mvnrepository.com/artifact/org.testng/testng -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
        </dependency>
        

        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        

        <!-- https://mvnrepository.com/artifact/org.uncommons/reportng -->
        <dependency>
            <groupId>org.uncommons</groupId>
            <artifactId>reportng</artifactId>
            <version>1.1.4</version>
        </dependency>
        

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/javax.mail/javax.mail-api -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>javax.mail-api</artifactId>
            <version>1.6.2</version>
        </dependency>


        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>


        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.17</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>openxml4j</artifactId>
            <version>1.0-beta</version>
        </dependency>


    </dependencies>
</project>

 

Click on Save button and all these dependencies should get started downloading.

 

Copy the chromedriver/geckodriver in the drivers package

 

 

Creating Page classes

 

Inside com.appliedselenium.pages package create the following classes:

  • LandingPage.java
  • ProductSearchPage.java
  • SignInPage.java
  • HomePage.java

Here, the most important thing is page navigation. We have already discussed the application flow in the second paragraph of this tutorial. Let us see into it in more detail in our page classes.

 

LandingPage.java class

 

To search a product, the user has to enter some text in the search box at the landing page and on click of Enter key Product Search Page is displayed. This can also be interpreted as searching a product at landing page returns product search page object.

Paste the following code to LandingPage.java class. This will complete our Test 1.

 

package com.appliedselenium.pages;

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

public class LandingPage {
    
    
    //Declare the driver
    WebDriver driver;
    
    
    //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();
    }
    

}

 

getTitle() – This method returns the title of Landing Page. We can verify this title in LandingPageTest class to make certain that title is correct.

searchProduct() – This method will enter dress in the search box, click on the search button and returns the ProductSearchPage object.

clickOnSignIn() – Similar to the above method, this method should help in clicking the Sign In button and returns the SignInPage object.

Before proceeding with the designing of other classes, let’s test the above methods first. Inside com.appliedselenium.tests package create a class LandingPageTest.java with the main method and paste the below code:

 

package com.appliedselenium.tests;

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

import com.appliedselenium.pages.LandingPage;

public class LandingPageTest {

    public static void main(String[] args) {

        
        //Set the path for chromedriver
        String filePath = System.getProperty("user.dir");

        System.setProperty("webdriver.chrome.driver", filePath + "/src/test/resources/com/appliedselenium/drivers/chromedriver");
        
        WebDriver driver = new ChromeDriver();
        
        //go to application
        driver.get("http://automationpractice.com/index.php");
        
        //Store the actual/ runtime title in some string
        String actualTitle = driver.getTitle();
        
        //Instantiate LandingPage class object
        LandingPage landingPage = new LandingPage();
        
        //Verify the titles
        if(landingPage.getTitle().equals(actualTitle)) {
            System.out.println("Title Matched - Test Passes");
        }else {
            System.out.println("Title doesn't match - Test Failed");
        }
        
        //Navigate to Product Search page
        landingPage.searchProduct();

        //Click on Sign In button
        landingPage.clickOnSignIn();
    }

}

 

If you execute the above code, it will generate below error. This is due to the driver object in LandingPage.java class. Our test class driver is not connected to the page class driver, hence it could not locate the web elements. 

 

Page Object Model error

 

To remove the above error, simply create a constructor of LandingPage.java class with WebDriver as a parameter. Update the LandingPage.java and LandingPageTest.java as below in bold:

 

package com.appliedselenium.pages;

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

public class LandingPage {
    
    
    //Declare the driver
    WebDriver driver;
    
    //Create constructor which accepts Webdriver object
    public LandingPage(WebDriver mdriver) {
        driver = mdriver;
    }
    
    //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();
    }
    

}

 

 

package com.appliedselenium.tests;

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

import com.appliedselenium.pages.LandingPage;

public class LandingPageTest {

    public static void main(String[] args) {

        
        //Set the path for chromedriver
        String filePath = System.getProperty("user.dir");

        System.setProperty("webdriver.chrome.driver", filePath + "/src/test/resources/com/appliedselenium/drivers/chromedriver");
        
        WebDriver driver = new ChromeDriver();
        
        //go to application
        driver.get("http://automationpractice.com/index.php");
        
        //Store the actual/ runtime title in some string
        String actualTitle = driver.getTitle();
        
        //Instantiate LandingPage class object
        LandingPage landingPage = new LandingPage(driver);
        
        //Verify the titles
        if(landingPage.getTitle().equals(actualTitle)) {
            System.out.println("Title Matched - Test Passes");
        }else {
            System.out.println("Title doesn't match - Test Failed");
        }
        
        //Navigate to Product Search page
        landingPage.searchProduct();

        //Click on Sign In button
        landingPage.clickOnSignIn();
    }

}

 

Executing the above code should:

  • open the browser
  • navigate to the demo application
  • verify if the titles are equal, this completes our Test 1
  • search with string dress 
  • Click on Sign In button

 

ProductSearchPage.java class

 

The second test is to verify that the searched product dress should be found. Go to the application and search for dressAssume below-highlighted dress should be displayed in the search results.

 

Product Search Page Result

 

We will write a script which will verify if the text “Printed Summer Dress” is displayed for the first search result. We have already written a method searchProduct() in LandingPage.java class which search for the keyword dress and returns the ProductSearchPage class object.

Similar to LandingPage.java this class also consist of a constructor to refer the driver instance. We will write a method in this class which should return the text of the first test result. This text will be verified in our test class.

Below is the code for ProductSearchPage.java class:

 

package com.appliedselenium.pages;

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

public class ProductSearchPage {
    
    WebDriver driver;
    
    //constructor to get the reference of driver object
    public ProductSearchPage(WebDriver driver) {
        this.driver = driver;
    }
    
    
    //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;
    }

}

 

Below is the updated code for LandingPageTest.java:

 

package com.appliedselenium.tests;

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

import com.appliedselenium.pages.LandingPage;
import com.appliedselenium.pages.ProductSearchPage;

public class LandingPageTest {

    public static void main(String[] args) {

        //Declare an object of class ProductSearchPage class
        ProductSearchPage pr;
        
        //Set the path for chromedriver
        String filePath = System.getProperty("user.dir");

        System.setProperty("webdriver.chrome.driver", filePath + "/src/test/resources/com/appliedselenium/drivers/chromedriver");
        
        WebDriver driver = new ChromeDriver();
        
        //go to application
        driver.get("http://automationpractice.com/index.php");
        
        //Store the actual/ runtime title in some string
        String actualTitle = driver.getTitle();
        
        //Instantiate LandingPage class object
        LandingPage landingPage = new LandingPage(driver);
        
        //Instantiate ProductSearchPage class object
        pr = new ProductSearchPage(driver);
        
        //Verify the titles
        if(landingPage.getTitle().equals(actualTitle)) {
            System.out.println("Title Matched - Test Passes");
        }else {
            System.out.println("Title doesn't match - Test Failed");
        }
        
        //Navigate to Product Search page
        landingPage.searchProduct();
        
        //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();*/
        
        
    }

}

 

Since ProductSearchPage constructor takes driver as an argument, update the below line in LandingPage.java class:

 

package com.appliedselenium.pages;

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

public class LandingPage {
    
    
    //Declare the driver
    WebDriver driver;
    
    //Create constructor which accepts Webdriver object
    public LandingPage(WebDriver mdriver) {
        driver = mdriver;
    }
    
    //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(driver);
        
    }
    
    //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();
    }
    

}

 

Running the LandingPageTest.java class should now execute 2 test cases.

 

SignInPage.java class

 

This class will contain a method to enter the user name, password and click on Sign In button. After the login is successful, the home page is displayed as follows:

 

SignIn Page result

 

Below is the code for SignInPage.java class:

 

package com.appliedselenium.pages;

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

public class SignInPage {

    WebDriver driver;
    
    public SignInPage(WebDriver driver) {
        this.driver = driver;
    }
    
    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(driver);
        
    }

}

 

Update the LandingPage.java class for clickOnSignIn() method to include the driver as the parameter(like we did for ProductSearchPage.java class).

To verify the third test, let’s create a HomePage.java class and verify the user name after login.

 

HomePage.java class

 

HomePage.java class contains a method which returns the String value of user name. Below is the code:

 

package com.appliedselenium.pages;

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

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

}

 

Below is the updated code for LandingPageTest.java including all the 3 tests:

 

package com.appliedselenium.tests;

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

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) {

        //Declare an object of class ProductSearchPage class
        ProductSearchPage pr;
        SignInPage inPage;
        HomePage homePage;
        
        //Set the path for chromedriver
        String filePath = System.getProperty("user.dir");

        System.setProperty("webdriver.chrome.driver", filePath + "/src/test/resources/com/appliedselenium/drivers/chromedriver");
        
        WebDriver driver = new ChromeDriver();
        
        //go to application
        driver.get("http://automationpractice.com/index.php");
        
        //Store the actual/ runtime title in some string
        String actualTitle = driver.getTitle();
        
        //Instantiate LandingPage class object
        LandingPage landingPage = new LandingPage(driver);
        
        //Instantiate ProductSearchPage class object
        pr = new ProductSearchPage(driver);
        
        //Verify the titles
        if(landingPage.getTitle().equals(actualTitle)) {
            System.out.println("Title Matched - Test Passes");
        }else {
            System.out.println("Title doesn't match - Test Failed");
        }
        
        //Navigate to Product Search page
        landingPage.searchProduct();
        
        //Verify the text
        if(pr.getProductSearchResult().contains("Printed Summer Dress")) {
            System.out.println("Product Found");
        }else {
            System.out.println("Product Search Failed");
        }

        
        inPage = new SignInPage(driver);
        //Click on Sign In button
        landingPage.clickOnSignIn();
        inPage.userSignIn("abc11001@xyz.com", "abcxyz");
        
        homePage = new HomePage(driver);
        
        if(homePage.verifyCorrectLogin().equals("abx xyz")) {
            System.out.println("Login Successful");
        }else {
            System.out.println("Login Failed");
        }
        
        
    }

}

 

Looking at the scripts created so far, you must have noticed that there are lines of code in each class which are repetitive. This will introduce the concept of Base class or Parent Class.

The base or parent class contains the code which is required by all the classes. We will put all the repetitive code and some other things in the base class and other classes will extend the base class to make use of that code.

In our next tutorial, we will learn how to create a parent or base class and refactor our code.

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.

3 thoughts on “Page Object Model | Framework Design – Part 2

Leave a Reply

Your email address will not be published. Required fields are marked *