Useful Design Patterns in Selenium Webdriver script


In this blog, we are going to discuss about different test design patterns and which one do we need to adhere while writing the Selenium webdriver test scripts.

The most popular design patterns in Selenium are,
1) Singleton Pattern
2) Page object model

First we will look into the question - What is Design Pattern?
                 Design Pattern is the Programmer follows the good practices while writing program for the application or product to resolve/rectify the commonly occurring issues. In other words, It is a kind of strategy having structured program approach towards to show interactions and relationships between Classes and Objects.

We have different kinds of Design patterns with its own Pros and Cons. The Design pattern types are,

  • Creational Pattern - Practice of initiating the class object without using new operator for Object initiation.
  • Structural Pattern - Practice of implementing inheritance in between Class, Object and interface to achieve new functionalities.
  • Behavioral Pattern - Practice of implementing interaction between Objects.
  • Concurrency Pattern - Practice of handling data members and methods in Multi threaded programs.

Forget to tell you, Singleton and Factory(or Page object model) patterns comes under Creational Pattern as both patterns deals with Object creation. Lets discuss those in detail,

Singleton Pattern - Ensure a class to have only one object in return. It is a simple and best way to create an object.  The class will create an object and let other classes to use that the object directly and strictly restrict the creation of the object using new operator.

The easiest implementation is having private constructor and a variable as place holder to store the value and a static method with a name getInstance().

public class Singleton {
   //create an object for this class
   private static Singleton instance = null;
   //make the constructor private so that this class cannot be instantiated
   private SingleObject(){}
   //method to make sure to maintain one object
   public static Singleton getInstance(){
        if (instance == null) {
                    instance = new Singleton();
}
        return instance;
   }

   public void showMessage(){
      System.out.println("Singleton Implemented");
   }
}
In other class, if we try to create an object for the class "Singleton" then it will through compile time error stating the object cannot be instantiated.

So, it will allow only to make use of the object.

Singleton objSingle = Singleton.getInstance();
objSingle.showMessage();

Output will be,
Singleton Implemented

Advantages,
  • It will remove unnecessary data members in the package and prefer to be global variable
  • It prevents race condition and provides thread safe implementation

In selenium, we used to invoke the specified browser as precondition before we execute our selenium scripts and we have handled this situation by adding IF conditions to classify & create the webdriver object related to the browsers within Test method. As best practice, try to create wrapper class around Webdriver to restrict the object creation and hiding the implementation from the outside world.

Example:
public class WebDriverSingleton {
   public static WebDriver driver;
   public static WebDriver getInstance() {
     if (driver == null) {
       driver = new FirefoxWebDriver();
     }
     return driver;
   }

}

Page Object Model : A page object is an encapsulation of the Page classes. It provides a user-like access to the web page and hides the implementation details of a page (web elements). The page object model can be implement with or without the PageFactory class.

First we see POM without PageFactory pattern,
Class LoginPage
{
 Webdriver driver = null;
 public LoginPage(Webdriver driver){
  this.driver = driver;
 }

 public LoginPage login(){
  driver.findElement(By.xpath("<USERNAME>")).sendkeys("xxx");
  driver.findElement(By.xpath("<PASSWORD>")).sendkeys("xxx");
  driver.findElement(By.xpath("<LOGINBUTTON>")).click();
  return new HomePage(driver);
 }
}

Class HomePage
{
 Webdriver driver = null;
 public HomePage(Webdriver driver){
  this.driver = driver;
 }
 public boolean verifyHomePage(){
    return AssertTrue(driver.findElement(By.xpath("<WelcomePag>")).getText(),"xxxWelcomeText");
 }
}

The test script to test is,
LoginPage loginPage = new LoginPage(driver);
loginPage.login();

you could see, whenever we calls the method to do some action on the webpage, we have to pass the driver project for element identification. It will look like we have achieved Page object model but some how it will mess up the whole approach. What if I say, Selenium provider shows a way to achieve this approach by adding PageFactory in their package.

Using page factory we can avoid passing webdriver object to each classes directly. PageFactory will allow you to find elements by using the annotations @FindBy, @FindBys and @FindAll without explicitly mentioning the findElements in your Page class. Lets re-write the above example with Page Factory,

Class LoginPage
{
 @FindBy(XPATH = "<USERNAME>")
 private WebElement userName;
 @FindBy(XPATH = "<PASSWORD>")
 private WebElement password;
 @FindBy(XPATH = "<LOGINBUTTON>")
 private WebElement loginButton;

 public LoginPage login(){
  userName.sendkeys("xxx");
  password.sendkeys("xxx");
  loginButton.click();
  return new PageFactory.initElements(driver, HomePage.class);
 }
}

Class HomePage
{
 @FindBy(XPATH = "<WelcomePageElement>")
 private WebElement welcomeTextElement;

 public boolean verifyHomePage(){
    return AssertTrue(welcomeTextElement.getText(),"xxxWelcomeText");
 }
}

The test script to test will be,
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
loginPage.login();


Hence, you can write your tests in a way a user would describe the tests without worrying the implementation :)








Popular posts from this blog

Selenium Webdriver Interview Questions with Answer

Selenium IDE Interview Questions with Answer

DLL to Jar file conversion