Automation testing framework is a way of trying to implement a base structure of developing test automation scenarios. Framework should be reusable for all projects, scalable for multiple technologies , maintainable for code development, understandable for code quality and workable for other application integrations.
Page Object Model (POM) is a main part of automation framework. POM is used for reduce the duplicate code for same methods, every page has to be own class file to maintain that page changes easily, each page has to be own instance because in test automation, pages have to be accessible. In Selenium, if you want to use POM pattern, you need to create base classes and use in Selenium PageFactory for user interface. In this article, you can learn that how to create a POM structure which has these properties that mentioned above, with Java coding example.
Base
This class is implemented by using Generics in Java. This helps to create flexible page class and these page class can interact with selenium drivers.
public <BPage extends BasePage> BPage GetInstance(Class<BPage> page) {
Object obj = PageControl.initElements(DriverManager.getDriver(), page);
return page.cast(obj);
}
Base Page
We can create abstract class for initializing page in each class. Because, this is a standart of page object model. In addition, it provides us simplicity and understandability.
public abstract class BasePage extends Base {
public <BPage extends BasePage> BPage As(Class<BPage> pageInstance) {
try {
return (BPage) this;
} catch (Exception e) {
e.getStackTrace();
}
return null;
}
}
Page Control
Page Control provides to initialize a page classes with own methods using Selenium libraries and Generics in Java.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
public class PageControl extends PageFactory {
public static <T> T initElements(WebDriver driver, Class<T> pageClassToProxy) {
try {
T page = pageClassToProxy.newInstance();
PageFactory.initElements(
new FieldDecorator(new DefaultElementLocatorFactory(driver)), page);
return pageClassToProxy.cast(page);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
PageContext
In this class, setter and getter methods of pages are implemented by using BasePage class. This allows us to control which page is current or setting current page is given page.
public class PageContext {
private static final ThreadLocal<BasePage> pageContext= new ThreadLocal<>();
public static BasePage getCurrentPage() {
return pageContext.get();
}
public static void setCurrentPage(BasePage driverThreadLocal) {
pageContext.set(driverThreadLocal);
}
}
DriverManager
We can get and set our selenium drivers into the threads. Because of this implementation, selenium drivers can use in pages separately.
public class DriverManager {
private static final ThreadLocal<WebDriver> driverThread = new ThreadLocal<>();
public synchronized static WebDriver getDriver() {
return driverThread.get();
}
public synchronized static void setDriver(WebDriver driver) {
driverThread.set(driver);
}
}
ExamplePage
This is an example of a page with selenium processes and creating instance of page. Furthermore, setting or getting a current page object as a ExamplePage easily.
public class ExamplePage extends BasePage {
private By loginButtonId = By.id("loginButton");
private By nextButtonId = By.id("next");
public ExamplePage clickLogin() {
/* selenium click login button xpath which find above
*/
return GetInstance(ExamplePage.class);
}
public ExamplePage clickLogin() {
/* selenium click DriverManager.getDriver().findElements(nextButtonId).click();
*/
PageContext.setCurrentPage(Base.GetInstance(ExamplePage.class));
return PageContext.getCurrentPage().As(ExamplePage.class);
}
}
These explanations and examples are only related with page object model with Selenium. If you would like to use this structure in your code, you have to modify these codes according to your project.
Thanks for your time ☺️
Amil Uslu