Skip to content
SDETRole
SDETRole

Selenium interview question

How do you implement the Page Object Model, and why do many teams avoid PageFactory?

intermediate 2–5 yrs #page-object-model#framework#pagefactory#design-patterns

Short answer

A Page Object wraps one page or component: private locators, public methods that express user intent, and no assertions about business rules. Many teams avoid PageFactory because its proxies cache poorly with dynamic DOMs, hide waits and add little over plain By locators.

Answer

The Page Object Model (POM) puts the knowledge of how to interact with a page in one class, so tests only express what the user does. When the UI changes, you update one class instead of 200 tests.

Principles I follow

  1. Locators are private. Tests never see By objects.
  2. Methods express user intent: login(user), addToCart(sku), not clickButton3().
  3. No business assertions inside page objects. They return data or state (getErrorMessage(), isLoaded()), and the test decides what is correct. This keeps page objects reusable across positive and negative tests.
  4. Navigation returns the next page object, giving a fluent, readable flow.
  5. Compose components. A header, a date picker or a product card used on many pages becomes its own class, rather than duplicated across pages.
  6. Waits live inside page methods, so tests stay free of synchronisation noise.
public class LoginPage {
    private static final By EMAIL = By.cssSelector("[data-testid='email']");
    private static final By PASSWORD = By.cssSelector("[data-testid='password']");
    private static final By SUBMIT = By.cssSelector("[data-testid='login-submit']");
    private static final By ERROR = By.cssSelector("[role='alert']");

    private final WebDriver driver;
    private final WebDriverWait wait;

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    public DashboardPage loginAs(String email, String password) {
        submit(email, password);
        return new DashboardPage(driver);
    }

    public LoginPage loginExpectingError(String email, String password) {
        submit(email, password);
        wait.until(ExpectedConditions.visibilityOfElementLocated(ERROR));
        return this;
    }

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

    private void submit(String email, String password) {
        driver.findElement(EMAIL).sendKeys(email);
        driver.findElement(PASSWORD).sendKeys(password);
        driver.findElement(SUBMIT).click();
    }
}
@Test
void rejectsWrongPassword() {
    String error = new LoginPage(driver)
        .loginExpectingError("qa@example.com", "wrong")
        .errorMessage();
    assertEquals("Invalid email or password", error);
}

Why many teams avoid PageFactory

PageFactory.initElements with @FindBy fields still works in Selenium 4, but it has drawbacks:

  • Fields are proxies that look up the element on every call, which is fine, until someone adds @CacheLookup, which returns a cached reference that goes stale as soon as the DOM re-renders.
  • The proxy model hides when lookups happen, which makes waiting logic and debugging less obvious.
  • @FindBy annotations need compile-time constant strings, so parameterised locators (a row for a given order ID) end up as separate By code anyway.
  • It adds framework magic without solving a real problem that plain By constants and a helper method don’t.

Plain By constants plus explicit waits are simpler and more predictable. PageFactory is not wrong, but if a codebase uses it I want to know the team understands the proxy behaviour.

Beyond pages

For large single-page apps, organising by component often beats organising by URL. Some teams also layer the Screenplay pattern on top (actors, tasks, questions) for very large suites; it adds structure at the cost of more classes.

What interviewers look for

  • Intent-level methods, private locators and a clear stance on assertions.
  • Component composition, not giant 2,000-line page classes.
  • A reasoned view on PageFactory rather than “it’s the standard”.

Common mistakes

  • Page objects that extend a base class with dozens of unrelated helpers (“god base page”).
  • Exposing WebElement getters so tests click raw elements, which defeats the encapsulation.

A strong answer covers

  • Encapsulates locators and exposes intent-level methods
  • Keeps assertions in tests (or limited to page state checks)
  • Components / fluent navigation return the next page object
  • PageFactory drawbacks: proxies, stale elements, CacheLookup, hidden waits
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →