Page Object Model and Page Factory in Selenium
What is Page Object Model in Selenium?
Page Object Model is a design pattern widely used in Selenium automation testing. The primary goal of POM is to create an abstraction layer between the test scripts and the web pages under test. In simpler terms, each web page in the application is represented as a Java class, encapsulating the locators and methods associated with that page.
Advantages of Page Object Model
Code Reusability: With POM, web elements and their corresponding methods are encapsulated within page classes. This makes it easy to reuse code across different test scripts.
Enhanced Readability: The separation of concerns in POM enhances code readability. Test scripts focus on high-level actions, while page classes handle the implementation details.
Easy Maintenance: Any changes in the UI can be accommodated by updating the corresponding page class, avoiding the need to modify multiple test scripts.
Improved Collaboration: POM facilitates collaboration between developers and testers as they work on distinct components of the automation framework.
Implementing POM in Selenium Project
Let's walk through a basic example of implementing POM in a Selenium project using Java.
Sample Project Structure for POM:
src/main/java/pages: Package containing page classes
src/test/java/tests: Package containing test scripts
src/test/resources: Configuration files, test data, etc.
Example: LoginPage.java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage {
private WebDriver driver;
// Locators
private By usernameField = By.id("username");
private By passwordField = By.id("password");
private By loginButton = By.id("loginButton");
// Constructor
public LoginPage(WebDriver driver) {
this.driver = driver;
}
// Methods
public void enterUsername(String username) {
driver.findElement(usernameField).sendKeys(username);
}
public void enterPassword(String password) {
driver.findElement(passwordField).sendKeys(password);
}
public void clickLoginButton() {
driver.findElement(loginButton).click();
}
}
Example: LoginTest.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class LoginTest {
@Test
public void loginTest() {
WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
LoginPage loginPage = new LoginPage(driver);
loginPage.enterUsername("user123");
loginPage.enterPassword("pass456");
loginPage.clickLoginButton();
// Additional assertions and test steps
}
}
What is Page Factory in Selenium?
While POM provides a structured approach, Page Factory takes it a step further by introducing the concept of annotations. Page Factory is an extension of POM and is used to initialize page objects and elements automatically.
Implementing Page Factory in Selenium Project
Let's extend our previous example to incorporate Page Factory.
Sample Project Structure for Page Factory:
src/main/java/pages: Package containing page classes
Example: LoginPage.java with Page Factory
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
private WebDriver driver;
// Locators using Page Factory annotations
@FindBy(id = "username")
private WebElement usernameField;
@FindBy(id = "password")
private WebElement passwordField;
@FindBy(id = "loginButton")
private WebElement loginButton;
// Constructor with Page Factory initialization
public LoginPage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
// Methods
public void enterUsername(String username) {
usernameField.sendKeys(username);
}
public void enterPassword(String password) {
passwordField.sendKeys(password);
}
public void clickLoginButton() {
loginButton.click();
}
}
Difference between Page Object Model & Page Factory in Selenium
Feature | Page Object Model (POM) | Page Factory |
Initialization of Elements | Manual initialization of elements in the constructor. | Automated initialization using PageFactory.initElements(driver, this). |
Boilerplate Code | Requires explicit code for element initialization. | Reduces boilerplate code; elements are initialized automatically. |
Annotations | Does not use annotations for element identification. | Leverages annotations such as @FindBy for element identification. |
Code Readability | Code may be more verbose due to explicit initialization. | Code is cleaner and more readable with automated initialization. |
Flexibility | Provides flexibility in choosing when and how to initialize elements. | Promotes consistency by standardizing element initialization. |
Ease of Maintenance | May require updates across multiple constructors if element locators change. | Centralized initialization reduces the impact of changes to locators. |
Initialization Control | Developers have control over when and how elements are initialized. | Initialization is automated, reducing manual intervention. |
Conclusion
By adopting these design patterns, Selenium practitioners can build scalable and efficient automation frameworks that stand the test of time, ensuring the success of their testing endeavours.