Page Classes With By Fields

A LoginPage

The modern, recommended style: keep locators as private final By fields and find the element when the action runs. The page receives the driver in its constructor.

package com.shopease.pages;

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

public class LoginPage {
    private final WebDriver driver;

    private final By email = By.id("email");
    private final By password = By.id("password");
    private final By loginButton = By.id("login-btn");
    private final By error = By.cssSelector(".error-message");

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

    public LoginPage open() {
        driver.get("https://shopease.example.com/login");
        return this;
    }

    public HomePage loginAs(String user, String pwd) {
        driver.findElement(email).sendKeys(user);
        driver.findElement(password).sendKeys(pwd);
        driver.findElement(loginButton).click();
        return new HomePage(driver);          // the next page the user lands on
    }

    public String errorText() {
        return driver.findElement(error).getText();
    }
}

The Test Uses Only Page Methods

public class LoginTest extends BaseTest {

    @Test
    public void validUserSeesWelcomeMessage() {
        HomePage home = new LoginPage(driver).open().loginAs("[email protected]", "Secret@123");
        Assert.assertEquals(home.welcomeText(), "Welcome, Asha");
    }

    @Test
    public void wrongPasswordShowsError() {
        LoginPage login = new LoginPage(driver).open();
        login.loginAs("[email protected]", "wrong");
        Assert.assertEquals(login.errorText(), "Invalid email or password");
    }
}

Example

Run the class:

mvn test -Dtest=LoginTest

Example output

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.shopease.tests.LoginTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.412 s - in com.shopease.tests.LoginTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

Page Class Rules

  • Locators are private: tests never touch them.
  • Methods describe user intent (loginAs, addToCart), not clicks (clickButton3).
  • A method that navigates returns the next page object; a method that stays returns this.
  • No assertions inside page classes (return values; the test decides pass/fail). Some teams allow small "is loaded" checks.
  • Large pages are split into components: HeaderComponent, CartDrawer, ProductCard.