I am a beginner in learning selenium Webdriver. I am not able to understand how page object and factory models works and how it can be beneficial?
Kindly help me explain it with detailed explanation.
Software Quality Assurance & Testing Stack Exchange is a question and answer site for software quality control experts, automation engineers, and software testers. It only takes a minute to sign up.
Sign up to join this communityI am a beginner in learning selenium Webdriver. I am not able to understand how page object and factory models works and how it can be beneficial?
Kindly help me explain it with detailed explanation.
PageObjects
The code of automated test cases should be easy to understand and not too complex. If a test fails, we want to know why and this as soon as possible. To allow this exists PageObjects. PageObjects are classes that contains WebElements and every actions associated with those.
A PageObject looks like this:
class HomePage {
WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
}
// Find a single element
@FindBy(id="home-menu-entry")
WebElement homeMenuEntry;
public void clickHomeMenuEntry() {
homeMenuEntry.click();
}
// Find several elements
@FindBy(className="menu-entry")
List<WebElement> menuEntries;
// More actions and elements
}
Usage of PageFactory and PageObject
class TestSomething {
public void testMethod() {
// Initial driver.
// Use PageFactory to init elements.
HomePage hp = PageFactory.initElements(driver, HomePage.class);
// Use PageObject to execute action.
hp.clickHomeMenuEntry();
// Assertions or more actions.
}
}
You also can put the PageFactory.initElements();
into the constructor and create just an HomePage
object instead of calling the PageFactory
method.
Important: If you call initElements()
all elements will be initialized, not later if you use them.
How to organize this?
I do the following: Each page has a PageObject, that represent these. But some components of a page are present on many pages. For this case I create for each component additional classes. Example:
Useful Links
POM
, where's the composition or inheritance? If you're dealing with fragments, how are you instantiating and initializing Header
and Footer
?
Page Factory Pattern is like an extension to Page Object Model , but Page Factory is much enhanced model. To start with, we just need to import package org.openqa.selenium.support.PageFactory
"Factory class can be used to make using Page Objects simpler and easier".
We use Page Factory pattern to initialize web elements which are defined in Page Objects.
We should initialize page objects using initElements()
method from PageFactory Class as below, Once we call initElements() method, all elements will get initialized. PageFactory.initElements()
static method takes the driver instance of the given class and the class type, and returns a Page Object with its fields fully initialized.
public HompePage(WebDriver driver)
{
this.driver = driver;
PageFactory.initElements(driver, this);
}
Now question arise why we use Constructor?
Solution is=>
We should preferably use a constructor which takes a WebDriver instance as its only argument or falling back on a no-arg constructor. An exception will be thrown if the class cannot be instantiated.
Page Factory will initialize every WebElement variable with a reference to a corresponding element on the actual web page based on “locators” defined.
Check below code by using Simple POM
public class BasePage
{
private By username = By.id("username");
private By password = By.id("password");
private By loginBtn = By.name("loginbtn");
public void userLogin(String userName, String password)
{
driver.findElement(username).sendKeys("testuser");
driver.findElement(password).sendKeys("testpassword");
driver.findElement(loginBtn).click();
}
}
By using using Page Factory:
public class BasePage {
@FindBy(id= "username") private WebElement userName;
@FindBy(id= "password") private WebElement password;
@FindBy(id= "login") private WebElement loginBtn;
public void userLogin(String userName, String password) {
userName.sendKeys(userName);
password.sendKeys(password);
loginBtn.click();
}
}
In very simple terms, the explanation for page objects is as follows: A separate class (per page) which lists all the objects in a page and the allowed operations that can be performed by them can be created. And whenever you need to perform any tests on that particular page in your webapp, you write the test to first import the page, and thereafter, perform all the allowed functions on that page to execute your tests.
In effect, there is a clear definition of the page with its objects and actions that can be performed on each object, and a separation of the tests that use those methods.
A very obvious benefit would be that anyone who looks through the page object class will be able to know what objects reside on that page and what operation can be performed by each object. A test automation engineer working on contract or new to your project only needs to know the location of the page object class and can help automate tests without having to go through any extensive training.
Hope this gives a bit more clarity on page objects. Cheers!
Page objects is a well known design pattern, widely accepted by the automation engineers, to create separate class file for each page of the application to group all the elements as properties and their behaviors / business functionalities as methods of the class. But it might not be a great idea always, especially when the page has more / different sets of elements / complex element like a grid / calendar widget / a HTML table etc.
When you try to incorporate all the elements of a page in one single page class, it becomes too big to read, maintain etc. The class might contain too many responsibilities to handle. It should be restructured and broken into smaller classes.
I would expect my page objects to satisfy the Single Responsibility Responsible.
You can find more info here.
graphene
; in a sense, it promotes graphene
-- which might be wonderful. But, it kinda does. Still, it's a good answer. And, a good link.