Page object Model - simon-sai/selenium-appium-java GitHub Wiki

In Selenium Java with Cucumber, the Page Object Model (POM) design pattern separates the test logic from the page structure by creating classes that represent web pages. This makes your tests easier to maintain, improves code readability, and promotes reusability.

(All the examples below are not from the framework; they are simple versions to help understand the concept)

Purpose of POM :

  • Separation of concerns: Keeps page element locators and actions separate from the test logic.
  • Reusability: Pages and their methods can be reused across different test cases.
  • Maintainability: If locators change, you only need to update them in one place (the page class), rather than in multiple tests.
  • Simplified test code: Test code becomes more readable and maintainable, focusing only on actions, not on how those actions are performed.

Code Example:

  1. Page Object Class (LoginPage.java)
package pages;

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

public class LoginPage {

    WebDriver driver;

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

    // Page elements (locators)
    By usernameField = By.id("username");
    By passwordField = By.id("password");
    By loginButton = By.id("loginButton");

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

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

    public void clickLoginButton() {
        WebElement loginBtn = driver.findElement(loginButton);
        loginBtn.click();
    }
}
  1. Step Definition Class (LoginSteps.java)
package stepDefinitions;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.*;
import pages.LoginPage;

public class LoginSteps {

    WebDriver driver;
    LoginPage loginPage;

    @Given("user is on login page")
    public void user_is_on_login_page() {
        // Initialize WebDriver
        driver = new ChromeDriver();
        driver.get("https://example.com/login");

        // Initialize the LoginPage object
        loginPage = new LoginPage(driver);
    }

    @When("user enters {string} and {string}")
    public void user_enters_username_and_password(String username, String password) {
        loginPage.enterUsername(username);
        loginPage.enterPassword(password);
    }

    @And("clicks on login button")
    public void clicks_on_login_button() {
        loginPage.clickLoginButton();
    }

    @Then("user is navigated to the home page")
    public void user_is_navigated_to_the_home_page() {
        // Verify navigation to home page
        // Example assertion could be placed here
        driver.quit();
    }
}

Explanation:

  1. Page Class (LoginPage.java):
  • The By locators for username, password, and login button are defined as class fields.
  • This class encapsulates the actions of interacting with the login page (entering username/password, clicking login).
  1. Step Definitions (LoginSteps.java):
  • The step definitions use the LoginPage class to interact with the login page.
  • Each step is focused on a specific action: navigating to the login page, entering credentials, clicking the login button, and verifying the result.

By structuring your test this way, if any web element on the login page changes, only the locators in the LoginPage.java file need to be updated, leaving the test steps unaffected.