0
0
Selenium-pythonHow-ToBeginner · 4 min read

How to Use Page Factory Pattern in Selenium for Cleaner Tests

Use the PageFactory.initElements() method to initialize web elements annotated with @FindBy in your page object class. This pattern helps keep locators and actions organized, making Selenium tests easier to read and maintain.
📐

Syntax

The Page Factory pattern uses the @FindBy annotation to locate web elements and PageFactory.initElements() to initialize them. You declare web elements as fields in a class and annotate them with locator strategies.

  • @FindBy: Defines how to find the element (e.g., by id, name, xpath).
  • PageFactory.initElements(driver, this): Initializes all annotated elements in the class.
java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class PageObject {
    @FindBy(id = "elementId")
    private WebElement element;

    public PageObject(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void clickElement() {
        element.click();
    }
}
💻

Example

This example shows a simple login page object using Page Factory. It locates username, password fields, and login button, then performs a login action.

java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class LoginPage {
    @FindBy(id = "username")
    private WebElement usernameField;

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

    @FindBy(id = "loginBtn")
    private WebElement loginButton;

    public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void login(String username, String password) {
        usernameField.sendKeys(username);
        passwordField.sendKeys(password);
        loginButton.click();
    }

    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com/login");

        LoginPage loginPage = new LoginPage(driver);
        loginPage.login("user1", "pass123");

        System.out.println("Login attempted");
        driver.quit();
    }
}
Output
Login attempted
⚠️

Common Pitfalls

  • Not calling PageFactory.initElements() in the constructor causes elements to be null.
  • Using incorrect locator strategies in @FindBy leads to NoSuchElementException.
  • Trying to interact with elements before the page loads can cause failures; use waits as needed.
  • Declaring web elements as public instead of private breaks encapsulation.
java
/* Wrong way: Missing initElements call */
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class WrongPage {
    @FindBy(id = "btn")
    private WebElement button;

    public WrongPage(WebDriver driver) {
        // Missing PageFactory.initElements(driver, this);
    }

    public void clickButton() {
        button.click(); // button is null, causes NullPointerException
    }
}

/* Right way: Initialize elements */
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class RightPage {
    @FindBy(id = "btn")
    private WebElement button;

    public RightPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void clickButton() {
        button.click();
    }
}
📊

Quick Reference

ConceptDescriptionExample
@FindByAnnotation to locate elements@FindBy(id = "username")
PageFactory.initElementsInitializes annotated elementsPageFactory.initElements(driver, this);
WebElementRepresents a UI elementprivate WebElement loginButton;
EncapsulationKeep elements private and provide methodsprivate WebElement button; public void click() {...}

Key Takeaways

Always call PageFactory.initElements(driver, this) in your page object constructor.
Use @FindBy annotations to declare web elements clearly and maintainably.
Keep web elements private and provide public methods to interact with them.
Ensure correct locator strategies to avoid element not found errors.
Use waits to handle page load timing before interacting with elements.