Page Object Model

What is the Page Object Model and why use it?

POM is a design pattern where each page (or component) has a class that holds its locators and exposes actions as methods. Tests call those methods instead of using driver.findElement directly.

  • A changed locator is fixed in one place.
  • Tests read like test cases: loginPage.loginAs(user).
  • Waits and common steps are reused; less duplicated code.
public class LoginPage extends BasePage {
    private final By email = By.id("email");
    private final By password = By.id("password");
    private final By loginBtn = By.id("login-btn");

    public LoginPage(WebDriver driver) { super(driver); }

    public HomePage loginAs(String user, String pwd) {
        type(email, user);
        type(password, pwd);
        click(loginBtn);
        return new HomePage(driver);
    }
}

What is the difference between POM and PageFactory?

POM is the design pattern. PageFactory is a Selenium helper class that initialises @FindBy WebElement fields with lazy proxies (PageFactory.initElements(driver, this)). You can implement POM with or without PageFactory.

Today most teams prefer By fields: they work naturally with ExpectedConditions.visibilityOfElementLocated, allow dynamic locators, and avoid stale proxies (especially with @CacheLookup).

Should page classes contain assertions?

Generally no. Page methods perform actions and return data (cartCount(), errorText()); the test asserts. This keeps pages reusable for both positive and negative tests. An accepted exception is a small "page is loaded" check in the constructor (e.g. waiting for the page header) so that a wrong navigation fails early with a clear message.