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
@FindByleads toNoSuchElementException. - Trying to interact with elements before the page loads can cause failures; use waits as needed.
- Declaring web elements as
publicinstead ofprivatebreaks 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
| Concept | Description | Example |
|---|---|---|
| @FindBy | Annotation to locate elements | @FindBy(id = "username") |
| PageFactory.initElements | Initializes annotated elements | PageFactory.initElements(driver, this); |
| WebElement | Represents a UI element | private WebElement loginButton; |
| Encapsulation | Keep elements private and provide methods | private 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.