What is POM?
- Page Object Model is a design pattern to create Object Repository for web UI elements.
- Under this model, for each web page in the application, there should be corresponding page class.
- This Page class will find the WebElements of that web page and also contains Page methods which perform operations on those WebElements.
- Name of these methods should be given as per the task they are performing, i.e., if a loader is waiting for the payment gateway to appear, POM method name can be waitForPaymentScreenDisplay().
Advantages of POM
- Page Object Patten says operations and flows in the UI should be separated from verification. This concept makes our code cleaner and easy to understand.
- The Second benefit is the object repository is independent of test cases, so we can use the same object repository for a different purpose with different tools. For example, we can integrate POM with TestNG/JUnit for functional Testing and at the same time with JBehave/Cucumber for acceptance testing.
- Code becomes less and optimized because of the reusable page methods in the POM classes.
- Methods get more realistic names which can be easily mapped with the operation happening in UI. i.e. if after clicking on the button we land on the home page, the method name will be like 'gotoHomePage()'.
Assume that in our application we have a login page which offers regular log in functionality. We can create a page object for login page that will represent all login methods as actions, Web page looks like below where the constructor is accepting the WebDriver instance.
import org.openqa.selenium.WebDriver;
public class LoginPage {
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
}
Now after making our basic Page model for login and initializing the constructor which is accepting the WebDriver instance and we can start adding our methods which will serve as functionalities our login page offers. Our login page contains a login method which returns us the Home Page after login. ###LoginPage
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage {
private WebDriver driver;
private static final String LOGIN_PAGE_URL = "https://www.facebook.com/";
private static final By USERNAME_INPUT = By.name("email");
private static final By PASSWORD_INPUT = By.name("pass");
private static final By LOG_IN_BUTTON = By.id("loginbutton");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public LoginPage open() {
driver.get(LOGIN_PAGE_URL);
return this;
}
public HomePage loginAs(String username, String password) {
driver.findElement(USERNAME_INPUT).sendKeys(username);
driver.findElement(PASSWORD_INPUT).sendKeys(password);
driver.findElement(LOG_IN_BUTTON).click();
return new HomePage(driver);
}
}
###HomePage
import org.openqa.selenium.WebDriver;
public class HomePage {
private WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
}
}
Why should we use page objects?
They reduce the amount of duplicated code. If there is some change in the website or mobile User interface, in the perfect situation we need to apply the fix in only one place. Page objects increase code readable because they make the test easier to understand. They hide the details of the UI structure from the tests so we can clearly see the logic and the intention of the test. So, The public methods represent the services that the page offers and Page objects shouldn’t expose the internals of the page.
How to Use Page Object Class in Test
With Page Object our test are able to log in without worrying how the steps and functionality is implemented because it shouldn’t matter to the test. So lets create a simple implementation of our Login Page in our Test.
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class LoginTest {
private WebDriver driver;
private HomePage homePage;
@BeforeClass(alwaysRun = true)
public void setUp() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
@Test(description = "Open Facebook Page and Login with username and password")
public void loginFacebookTest() {
LoginPage loginPage = new LoginPage(driver);
homePage = loginPage.open().loginAs("username", "password");
}
}