Selenium – Page Object Model – Java

There are several ways to set up your web (selenium) test automation. You can directly create test functions where the web elements are invoked. This can be done quick, but is quite dirty and at some point, the code base will grow, and maintainability will be an issue. Furthermore, it doesn’t have any structure and redundancy of code and debug “horror” will overwhelm.

The Page Object Model (POM) Design pattern offers a solution where the idea behind the design, is to create for every webPage (or part of the webPage) a representing class.  The benefit of this design is that the class contains methods (functional names) which are mimicking the web page elements. The advantage is that POM class is reusable. It also avoids web-elements redundancy by having the web elements assigned in one class, and it has a logical structure, which make it easier to test the application.  Let’s clarify this with an example.

Let’s assume the application under test has a login webpage, and it looks like the picture below:Screen Shot 2019-07-12 at 16.23.44

There are at least three web elements involved to pass the login screen, which are enumerated below:

  1. Username – input text field type
  2. Password – input text field type
  3. Login –  button type

Let’s start creating the POM class.  To do so, the mindset needs to be changed, almost thinking like a developer that is building a web page. There are at least the following functionalities:

  1. EnterUsername
  2. EnterPassword
  3. ClickLogin

It will result to the following java class:

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

public class LoginPage {

    private WebDriver driver;

    public LoginPage(WebDriver driver){
        this.driver = driver;
    }


    public void enterUsername(String username){
        WebElement usernameInputText = driver.findElement(By.name("username"));
        usernameInputText.sendKeys(username);
    }

    public void enterPassword(String password){
        WebElement passwordInputText = driver.findElement(By.name("password"));
        passwordInputText.sendKeys(password);
    }

    public void clickLogin(){
        WebElement loginButton = driver.findElement(By.name("loginButton"));
        loginButton.click();
    }

    public void loginAs(String username, String password){
        enterUsername(username);
        enterPassword(password);
        clickLogin();
    }

}

All the functionalities mentioned above have been coded. The Page Object Model class should not have any assertion. That’s being accomplished in another class that’s dedicated for executing the test cases (e.g. testng class). Like below example:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;

public class TestPOMSelenium {

    private WebDriver driver;

    @BeforeClass
    public void init(){
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    @Test(testName = "validLoginUser")
    public void tstSeleniumBrowser(){
        driver.get("https://yoururl");

        LoginPage loginPage = new LoginPage(driver);

        loginPage.enterUsername("testUser");
        loginPage.enterPassword("testPassword");
        loginPage.clickLogin();

        //or a shortcut, by doing it with one method
        //loginPage.loginAs("testUser","testPassword");

    }

    @AfterClass
    public void cleanup(){
        if(driver !=null)
            driver.quit();
    }

}

This is the benefit of using POM class. The web-elements and other logic are “hidden” in the POM class, and you are only testing/asserting the functionality in almost plain english.

Let’s go one step further and do some assertion. The assertion is that the login has passed if the main page is displayed. Let’s assume the main page looks like this:

Screen Shot 2019-07-12 at 16.43.44

Again the Page Object Model comes into play. This main page also needs it own Class. To keep it very simple, only the following functionalities are identified:

  • navigateToSearchCustomer
  • navigateToAddCustomer
  • navigateToUserManagement
  • getHeaderVersion

It will result to the following class:

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

public class MainPage {

    private WebDriver driver;

    public MainPage(WebDriver driver){
        this.driver = driver;
    }

    public void navigateToSearchCustomer(){
        WebElement searchCustomerBtn = driver.findElement(By.name("searchCustomerBtn"));
        searchCustomerBtn.click();
    }

    public void navigateToAddCustomer(){
        WebElement addCustomerBtn = driver.findElement(By.name("addCustomerBtn"));
        addCustomerBtn.click();
    }

    public void navigateToUserManagement(){
        WebElement usrMngmtBtn = driver.findElement(By.name("usrMngmtBtn"));
        usrMngmtBtn.click();
    }

    public String getHeaderVersion(){
        WebElement versionHeader = driver.findElement(By.name("versionHeader"));
        return versionHeader.getText(); 
    }
}

There will be a slight change in the LoginPage (POM class), in the function clickLogin. It will return the MainPage object, as follows:

public MainPage clickLogin(){
    WebElement loginButton = driver.findElement(By.name("loginButton"));
    loginButton.click();
    return new MainPage(driver);
}

That’s the great part of Page Object Model. It’s a kind of abstraction, which will result to better testing. The assertion can be easily done. The clickLogin, will return a mainPage object. After that you can get the headerVersion and conduct an assertion on version number, see below example.

@Test(testName = "validLoginUser")
public void tstSeleniumBrowser(){
    driver.get("https://yoururl");

    LoginPage loginPage = new LoginPage(driver);

    loginPage.enterUsername("testUser");
    loginPage.enterPassword("testPassword");
    MainPage mainPage = loginPage.clickLogin();

    Assert.assertEquals(mainPage.getHeaderVersion(),"V0.0.03"); 
}

Hopefully, this has provided a bit of clarity in Page Object Model design. It will give you a more structured testing and better maintenance.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s