How to Implement Page Object Model with Spring Boot and Selenium

Photo by Trent Erwin on Unsplash

How to Implement Page Object Model with Spring Boot and Selenium

One of the biggest challenges of testing large web applications is writing maintainable and scalable test code. This is where the Page Object Model (POM) design pattern comes in handy. By using POM, we can create a structured and maintainable test suite for web applications that uses Selenium as a testing framework.

In this article, we will go through how we can implement the Page Object Model with Spring Boot and Selenium.

What is the Page Object Model (POM)?

The Page Object Model (POM) is a design pattern that is commonly used to define web pages with which we can interact using Selenium. This design pattern allows us to encapsulate a web page's elements, their locators, and methods that correspond to interactable user elements for that page.

This design pattern's main aim is to create a test suite that has the maintainability, readability and organization of production code, improving test suite scalability immensely.

Implementing POM For Spring Boot and Selenium

In this article, we will work with Spring Boot and Selenium to implement the Page Object Model. Our goal is to create a functional login automation test that logs the user into the application and asserts that the user was successfully logged in. We will create two page objects, the home page and login page, that will encapsulate their respective page elements.

Home Page Object

We begin by creating a class called HomePage.java. Here, we define the home page's elements, including their locators, and the actions the user can take on these elements.

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class HomePage {

    @Autowired
    private WebDriver driver;

    // Initialize the Page Object 
    public HomePage(WebDriver driver) {
        this.driver = driver;
    }

    // Locators
    private final By loginLink = By.linkText("Login");
    private final By usernameField = By.name("username");
    private final By passwordField = By.name("password");
    private final By submitButton = By.tagName("form");
    private final By successMessage = By.xpath("//div[@class='success']");
    private final By errorMessage = By.xpath("//div[@class='error']");

    // Actions
    public LoginPage clickLoginLink() {
        driver.findElement(loginLink).click();
        return new LoginPage(driver);
    }

    public String getSuccessMessage() {
        return driver.findElement(successMessage).getText();
    }

    public String getErrorMessage() {
        return driver.findElement(errorMessage).getText();
    }
}

Here, we have encapsulated the home page elements, including their locators, in the HomePage class, making use of the Page Factory pattern. We have defined locators for each element and created methods that correspond to the user actions on these elements. In addition to the locators, we have created methods to return success and error messages.

Login Page Object

Next, we create a class called LoginPage.java. Here, we will define the login page's elements, including their respective locators and user actions.

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class LoginPage {

    @Autowired
    private WebDriver driver;

    // Initialize the Page Object 
    public LoginPage(WebDriver driver) {
        this.driver = driver;
    }

    // Locators
    private final By usernameField = By.name("username");
    private final By passwordField = By.name("password");
    private final By submitButton = By.tagName("form");
    private final By errorMessage = By.xpath("//div[@class='error']");

    // Actions
    public void enterUsername(String username) {
        driver.findElement(usernameField).sendKeys(username);
    }

    public void enterPassword(String password) {
        driver.findElement(passwordField).sendKeys(password);
    }

    public HomePage clickSubmitButton() {
        driver.findElement(submitButton).submit();
        return new HomePage(driver);
    }

    public String getErrorMessage() {
        return driver.findElement(errorMessage).getText();
    }
}

Just as we did with HomePage, we have encapsulated the login page's elements, including their respective locators and corresponding user actions, in the LoginPage class.

Testing Login Functionality

With both page objects defined, we will now create a test to validate the login functionality. Here's how the relevant test class looks like:

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
public class LoginTest {

    @Autowired
    private WebDriver driver;

    @Test
    public void test() throws InterruptedException {
        HomePage homePage = new HomePage(driver);
        LoginPage loginPage = homePage.clickLoginLink();
        loginPage.enterUsername("admin");
        loginPage.enterPassword("admin123");
        homePage = loginPage.clickSubmitButton();
        String message = homePage.getSuccessMessage();
        assertEquals("Logged in successfully.", message);
    }
}

Here, we have defined a test class LoginTest. We initialized the HomePage and LoginPage classes which represents the home and login pages on the web application. We then simulate a user logging in by inputting valid credentials and then assert that we received the expected success message.

Conclusion

In this article, we saw how to implement the Page Object Model (POM) with Spring Boot and Selenium. The POM design pattern promotes creating a scalable, maintainable and structured test suite, and it has proven to be an effective design pattern for testing large web applications.

By encapsulating elements, their locators and methods that correspond to user interactions in separate classes, we can create a reusable and maintainable test suite with a structure and organization similar to production code.

Did you find this article valuable?

Support Rishav Trivedi by becoming a sponsor. Any amount is appreciated!