</>

Technology

Page Object Model

Difficulty

Beginner

Interview Question

What is the difference between Page Object Model and Page Factory in Selenium?

Answer

POM vs Page Factory

POM is the design pattern concept (separate page classes with locators + actions). Page Factory is a Selenium built-in tool that implements POM using annotations.

POM Without Page Factory (Manual)

Java
public class LoginPage {
    private WebDriver driver;

    // Locators defined as By objects
    private By emailInput    = By.id("email");
    private By passwordInput = By.id("password");
    private By loginBtn      = By.cssSelector("[data-testid='login-btn']");

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

    public void login(String email, String password) {
        // Element found EVERY TIME method is called
        driver.findElement(emailInput).sendKeys(email);
        driver.findElement(passwordInput).sendKeys(password);
        driver.findElement(loginBtn).click();
    }
}

Page Factory (Annotation-Based)

Java
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class LoginPage {
    private WebDriver driver;

    // @FindBy annotations replace By.id(), By.css() etc.
    @FindBy(id = "email")
    private WebElement emailInput;

    @FindBy(id = "password")
    private WebElement passwordInput;

    @FindBy(css = "[data-testid='login-btn']")
    private WebElement loginBtn;

    @FindBy(className = "error-msg")
    private WebElement errorMessage;

    // Multiple locators — tries each until one works
    @FindAll({
        @FindBy(id = "submit"),
        @FindBy(css = "button[type='submit']")
    })
    private WebElement submitBtn;

    // List of elements
    @FindBy(css = ".product-card")
    private List<WebElement> productCards;

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        // This initializes all @FindBy elements (lazy — located on first use)
        PageFactory.initElements(driver, this);
    }

    public void login(String email, String password) {
        emailInput.sendKeys(email);      // clean — no driver.findElement()
        passwordInput.sendKeys(password);
        loginBtn.click();
    }

    public String getErrorText() {
        return errorMessage.getText();
    }
}

@FindBy Locator Strategies

Java
@FindBy(id = "email")                          // By.id
@FindBy(name = "username")                      // By.name
@FindBy(className = "error-msg")               // By.className
@FindBy(tagName = "h1")                        // By.tagName
@FindBy(linkText = "Forgot Password")          // By.linkText
@FindBy(partialLinkText = "Forgot")            // By.partialLinkText
@FindBy(css = ".btn.btn-primary")              // By.cssSelector (most used)
@FindBy(xpath = "//button[@type='submit']")    // By.xpath

Key Differences

POM (Manual)Page Factory
Locator syntaxBy.id("email")@FindBy(id = "email")
Element typeLocated fresh each callProxy — located on first access
Stale elementLess issueCan get StaleElementReferenceException
InitializationNot neededPageFactory.initElements() required
ReadabilityGoodBetter (less boilerplate)
Dynamic elementsEasier to handleCan be tricky

When Stale Element is a Problem (Page Factory)

Java
// Page Factory can cause StaleElementReferenceException
// if DOM changes AFTER initElements() but BEFORE the element is used

// Solution: re-initialize on stale
public WebElement getElement(WebElement element) {
    try {
        return element;
    } catch (StaleElementReferenceException e) {
        PageFactory.initElements(driver, this);  // reinitialize
        return element;
    }
}

Follow AutomateQA

Related Topics