Aquarium Air Pump vs Filter: A Comprehensive Guide

aquarium air pump vs filter

Aquarium air pumps and filters are two essential components that work in tandem to maintain a healthy and thriving aquatic environment. While air pumps primarily focus on oxygenating the water, filters play a crucial role in removing waste, debris, and other contaminants, ensuring the overall water quality and the well-being of your aquatic inhabitants. Understanding … Read more

How to Precisely Adjust an Aquarium Air Pump: A Technical Playbook

how to adjust an aquarium air pump

Adjusting an aquarium air pump is a crucial task for maintaining the optimal oxygen levels and water circulation in your aquarium. This comprehensive guide will provide you with the technical know-how and quantifiable data to precisely control the air flow and pressure in your aquarium setup. Understanding Air Pump Specifications Before delving into the adjustment … Read more

5 Ways to Craft a Self-Inflating Air Mattress Pump

5 ways on how to make a self inflating air mattress pump

Creating a self-inflating air mattress pump can be a practical and cost-effective solution for those who frequently use air mattresses. This comprehensive guide delves into five distinct methods, each with its own set of technical specifications and design considerations. Whether you’re an avid camper, a frequent traveler, or simply someone who appreciates the convenience of … Read more

How to Build a Solar-Powered Air Pump for Your Aquarium: A Comprehensive DIY Guide

how can i build a solar powered air pump for my aquarium

Building a solar-powered air pump for your aquarium is a great way to create a sustainable and eco-friendly system to provide oxygen for your underwater ecosystem. This comprehensive guide will walk you through the step-by-step process of constructing a reliable and efficient solar-powered air pump, complete with technical specifications and quantifiable data points to ensure … Read more

How to Build a High Flow Aquarium Air Pump DIY

how to build a high flow aquarium air pump diy

Building a high-flow aquarium air pump DIY can be a rewarding project that allows you to customize the airflow and performance to meet the specific needs of your aquarium. This comprehensive guide will provide you with the necessary information and step-by-step instructions to create an efficient and effective high-flow air pump for your aquarium. Factors … Read more

Complete Page Object Model Framework -2021

1 3 191x300 1

In this tutorial, we will learn about the Page Object Model, and also we will design and develop the Page Object Model framework from scratch. 

We had discussed all the types of framework in Selenium, including Page Object Model , here we would go through in-depth.

We will design and develop the below features .

What is Page Object Model Framework design in Selenium  

Page Object Model is a Design Model for building Selenium test Automation, where we distribute our whole Application under test into small pages (sometimes a webpage is considered as a page, and sometimes a subpart of a Webpage is also considered as a Page ). Each of these pages is represented as a Java class, and the functionalities of the pages are written as different methods in the respective page’s Java class.

Let’s say you have a Gmail application which you will automate; hence the Gmail login page is there where you have few major functionalities such as login, create an account, etc.

Here we will create a java class as GmailLoginPage, and we will write methods named as performLogin() , createUserAccount, etc. 

Let’s say once you are logged in to your Gmail account, you have many features like inbox, sent items, trash, etc. Now here, for each module, you create a Java class and keep their functionalities as Java methods inside respective java classes. 

Why Page Object Model

Page Object Model is a very robust and advanced framework design model where you can take care of the below areas : 

Hybrid Page Object Model Framework Structure

In the previous tutorial, we understood the hybrid Page Object Model, and now we will design and develop a framework.

The architecture of the Page Object Model framework

We can simply create a maven project and incorporate the dependencies in POM.xml file thats required for the framework initially which looks like this one : 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
\txsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
\t<modelVersion>4.0.0</modelVersion>

\t<groupId>demo</groupId>
\t<artifactId>DemoAutomation</artifactId>
\t<version>0.0.1-SNAPSHOT</version>
\t<packaging>jar</packaging>

\t<name>DemoAutomation</name>
\t<url>http://maven.apache.org</url>
\t<properties>
\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
\t</properties>
\t<build>
\t\t<plugins>
\t\t\t<plugin>
\t\t\t\t<groupId>org.apache.maven.plugins</groupId>
\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>
\t\t\t\t<version>3.0</version>
\t\t\t\t<configuration>
\t\t\t\t\t<source>7</source>
\t\t\t\t\t<target>7</target>
\t\t\t\t</configuration>
\t\t\t</plugin>
\t\t\t<plugin>
\t\t\t\t<groupId>org.apache.maven.plugins</groupId>
\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>
\t\t\t\t<version>2.4.2</version>
\t\t\t\t<configuration>
\t\t\t\t\t<suiteXmlFiles>
\t\t\t\t\t\t<suiteXmlFile>testNg.xml</suiteXmlFile>
\t\t\t\t\t</suiteXmlFiles>
\t\t\t\t</configuration>
\t\t\t</plugin>
\t\t</plugins>
\t</build>
\t<reporting>
\t\t<plugins>
\t\t\t<plugin>
\t\t\t\t<groupId>org.reportyng</groupId>
\t\t\t\t<artifactId>reporty-ng</artifactId>
\t\t\t\t<version>1.2</version>
\t\t\t\t<configuration>
\t\t\t\t    <outputdir>/target/testng-xslt-report</outputdir>
\t\t\t\t    <sorttestcaselinks>true</sorttestcaselinks>
\t\t\t            <testdetailsfilter>FAIL,SKIP,PASS,CONF,BY_CLASS</testdetailsfilter>
\t\t\t\t    <showruntimetotals>true</showruntimetotals>
\t\t\t\t</configuration>
\t\t\t</plugin>
\t\t</plugins>
\t</reporting>
\t<dependencies>
\t\t<dependency>
\t\t\t<groupId>org.seleniumhq.selenium</groupId>
\t\t\t<artifactId>selenium-server</artifactId>
\t\t\t<version>2.53.0</version>
\t\t</dependency>
\t\t<dependency>
\t\t\t<groupId>org.testng</groupId>
\t\t\t<artifactId>testng</artifactId>
\t\t\t<version>6.8.1</version>
\t\t</dependency>
\t\t<dependency>
\t\t\t<groupId>org.apache.poi</groupId>
\t\t\t<artifactId>poi</artifactId>
\t\t\t<version>3.8</version>
\t\t</dependency>
\t\t<dependency>
\t\t\t<groupId>org.apache.poi</groupId>
\t\t\t<artifactId>poi-ooxml</artifactId>
\t\t\t<version>3.8</version>
\t\t</dependency>

\t\t<dependency>
\t\t\t<groupId>com.googlecode.json-simple</groupId>
\t\t\t<artifactId>json-simple</artifactId>
\t\t\t<version>1.1</version>
\t\t</dependency>

\t\t<dependency>
\t\t\t<groupId>net.sourceforge.jexcelapi</groupId>
\t\t\t<artifactId>jxl</artifactId>
\t\t\t<version>2.6</version>
\t\t</dependency>
\t</dependencies>
</project>

After that, we will build small modules and utilities, where we have attached this snapshot below just to provide high-level insights/view. We will build utilities one by one. 

Here are the below modules that we will develop; we have provided the code snippet for the same : 

DriverUtils – Page Object Model Framework

This module provides all the utilities and support to work with the various browsers (Chrome, Firefox, etc.).This utility is based on the Factory design pattern, as we discussed in the previous tutorial here.

package com.base.driverUtils;
import org.openqa.selenium.WebDriver;
public interface IDriver {
  public WebDriver init(String browserName);
}

Localdriver implementation, which will execute locally with Selenium Webdriver :

package com.base.driverUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
public class LocalDriver implements IDriver {
  public WebDriver init(String browserName) {
     switch (browserName) {
     case "firefox":
        return new FirefoxDriver();
     case "chrome":
        System.setProperty("webdriver.chrome.driver",
              "..\\\\DummyAutomation\\\\DriverExe\\\\chromedriver.exe");
        return new ChromeDriver();
     case "ie":
        System.setProperty("webdriver.ie.driver",
              "..\\\\DummyAutomation\\\\DriverExe\\\\IEDriverServer.exe");
        return new InternetExplorerDriver();
     default:
        return new FirefoxDriver();
     }
  }
}

Remote Webdriver: To work with a remote webdriver (such as Selenium Grid), you need a remote reference of the browser driver, which goes like : 

package com.base.driverUtils;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
public class RemoteDriver implements IDriver {
  DesiredCapabilities caps;
  String remoteHuburl;
  @Override
  public WebDriver init(String browserName) {
     switch (browserName) {
     case "firefox":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
        } catch (MalformedURLException e2) {
           // TODO Auto-generated catch block
           e2.printStackTrace();
        }
     case "chrome":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
        } catch (MalformedURLException e1) {
           // TODO Auto-generated catch block
           e1.printStackTrace();
        }
     case "ie":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.internetExplorer());
        } catch (MalformedURLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
     default:
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
        } catch (MalformedURLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
     }
     return null;
  }
 
}

Factory Driver class: This provides us the driver class (remote/local) object to initiate the browsers of your choice. We will take the type of driver(local or remote) and browser (chrome or firefox etc.) through the configuration file(we have used a properties file to keep the configurations, which we will share shortly )

package com.base.driverUtils;
public class DriverProvider {
  public IDriver getDriver(String typeOfDriverExecution){
     switch(typeOfDriverExecution){
     case "local":
        return new LocalDriver();
     case "remote":
        return new RemoteDriver();
     default :
        return new LocalDriver();
     }
  }
}

Now wherever you require the driver reference, you can simply create the object of the factory class object (DriverProvider in this case) and can initiate the driver browser instance.

Here is the very basic config file; you can create a properties file and store the values like this : 

modeOfExecution=local
browser=chrome
url=http://www.applicationUrl.com/

DataUtils-Page Object Model Framework: 

We have designed the data utilities here as the same Factory design pattern as we did from implementing the driver browser modules.

Here is the below code snippet for the same; in the framework, we have shown Excel utils and properties utils, you can enhance more to support other data utilities like YAML, PDF, etc.: 

The interface here goes like this: 

package com.base.dataUtils;
public interface IDataProvider {
  public Object[][] fetchDataSet(String... dataFileInfo);
  public String fetchData(String... dataFileInfo);
}

Here is the implementation for Excel Data provider

package com.base.dataUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelDataProvider implements IDataProvider {
  FileInputStream fis = null;
  private static XSSFWorkbook workBook = null;
  private static XSSFCell Cell;
  private static XSSFSheet sheet;
  public static String[][] excelDataSet = null;
  @Override
  public Object[][] fetchDataSet(String... dataFileInfo) {
     String excelFilePath = dataFileInfo[0];
     String excelSheetName = dataFileInfo[1];
     File file = new File(excelFilePath);
     try {
        fis = new FileInputStream(file);
     } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     try {
        workBook = new XSSFWorkbook(fis);
     } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     sheet = workBook.getSheet(excelSheetName);
     int ci, cj;
     int rowCount = sheet.getLastRowNum();
     int totalCols = sheet.getRow(0).getPhysicalNumberOfCells();
     excelDataSet = new String[rowCount][totalCols - 1];
     ci = 0;
     for (int i = 1; i <= rowCount; i++, ci++) {
        cj = 0;
        for (int j = 1; j <= totalCols - 1; j++, cj++) {
           try {
              excelDataSet[ci][cj] = getCellData(i, j);
           } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
           }
        }
     }
     return excelDataSet;
  }
  public static String getCellData(int RowNum, int ColNum) throws Exception {
     try {
        Cell = sheet.getRow(RowNum).getCell(ColNum);
        int dataType = Cell.getCellType();
        if (dataType == 3) {
           return "";
        }
        else if (dataType == XSSFCell.CELL_TYPE_NUMERIC) {
           int i = (int) Cell.getNumericCellValue();
           return Integer.toString(i);
        }
        else {
           String CellData = Cell.getStringCellValue();
           return CellData;
        }
     } catch (Exception e) {
        throw (e);
     }
  }
  @Override
  public String fetchData(String... dataFileInfo) {
     // TODO Auto-generated method stub
     return null;
  }
}

Properties Data provider : 

package com.base.dataUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDataProvider implements IDataProvider {
  FileInputStream fis=null;
  @Override
  public Object[][] fetchDataSet(String... dataFileInfo) {
     // TODO Auto-generated method stub
     return null;
  }
  @Override
  public String fetchData(String... dataFileInfo) {
     String dataValue;
     String pathToFile = dataFileInfo[0];
     String key = dataFileInfo[1];
     Properties properties = new Properties();
     try {
        fis=new FileInputStream(pathToFile);
        properties.load(fis);
     } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     dataValue = properties.getProperty(key);
     return dataValue;
  }
}

The factory class for this data Utilities

package com.base.dataUtils;
public class DataHelperProvider {
  public IDataProvider getDataHelperProvider(String typeOfDataHandler) {
     switch (typeOfDataHandler) {
     case "excel":
        return new ExcelDataProvider();
     case "properties":
        return new PropertiesDataProvider();
     }
     return null;
  }
}

WebAction utilities -Page Object Model Framework

In the utilities, we write all the utilities related to your Web actions like (click, sendkeys, screenshots, etc.), and we can utilize it in Page Methods to perform web actions to achieve the page functionalities as discussed earlier in this tutorial. 

Here is the code snippet for the WebAction Utilities : 

package com.base.webActionHelperUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class WebActionsHelperUtils {
  protected WebDriver driver;
  public WebActionsHelperUtils(WebDriver driver) {
     this.driver = driver;
  }
  public void safeClick(By element) {
     waitForElementToBeClickAble(element, 30);
     driver.findElement(element).click();
  }
  public List<WebElement> getElements(By elements) {
     return driver.findElements(elements);
  }
  public void waitForWebElementsToBeDisplayed(By elements, int timeOuts) {
     WebDriverWait wait = new WebDriverWait(driver, timeOuts);
     wait.until(ExpectedConditions.visibilityOfAllElements(getElements(elements)));
  }
  public void waitForElementToBeClickAble(By element, int timeOutSeconds) {
     WebDriverWait waitForElement = new WebDriverWait(driver, timeOutSeconds);
     waitForElement.until(ExpectedConditions.elementToBeClickable(element));
  }
  public void waitForElementToBeDisplayed(By element, int timeOuts) {
     WebDriverWait wait = new WebDriverWait(driver, timeOuts);
     wait.until(ExpectedConditions.visibilityOfElementLocated(element));
  }
  public void enterTextIntoElement(By element, String textToBeEntered) {
     driver.findElement(element).sendKeys(textToBeEntered);
  }
  public String getText(By element) {
     return driver.findElement(element).getText();
  }
  public String getAttribute(By element, String attribute) {
     return driver.findElement(element).getAttribute(attribute);
  }
  public boolean isSelected(By element) {
     boolean isElementSelected = false;
     if (driver.findElement(element).isSelected() == true) {
        isElementSelected = true;
     }
     return isElementSelected;
  }
  public void clearField(By element) {
     driver.findElement(element).clear();
  }
  public void implicitlyWait(int timeOuts) {
     driver.manage().timeouts().implicitlyWait(timeOuts, TimeUnit.SECONDS);
  }
  public boolean isElementPresent(By element) {
     try {
        driver.findElement(element);
        return true;
     } catch (Exception e) {
        return false;
     }
  }
  public void switchToTab(int indexOfTab) {
     ArrayList<String> tabs = new ArrayList<String>(driver.getWindowHandles());
     driver.switchTo().window(tabs.get(indexOfTab));
  }
}

Page Module utilities-Page Object Model Framework

Like we know, we have to create the Page class and keep the page functionalities in the page methods, so now let’s create the Page Module for the Page Object Model framework : 

Every Page Class again extends the WebAction Utils that we developed just now and implements the Page interfaces, where the page interfaces are nothing but the interfaces to keep the respective page’s Web Elements/locators.

Now Why we need interfaces to store the locators : 

Hence we used separate interfaces for separate page locators to store as by this approach; we solve all the above problem statements, which are time complexity, space complexity, and the clean and maintainable codebase as in interfaces, we don’t have to create objects to access locators.

package com.base.pageModules;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.base.commonUtils.JSonHandler;
import com.base.webActionHelperUtils.WebActionsHelperUtils;
import com.page.locatorModules.HomePageLocators;
public class HomePage extends WebActionsHelperUtils implements HomePageLocators {
  JSonHandler jsonHandler = new JSonHandler();
  public HomePage(WebDriver driver) {
     super(driver);
     this.driver = driver;
  }
  public void enterSearchdataToSearchField(String searchData) {
     waitForElementToBeClickAble(SEARCH_BOX, 10);
     enterTextIntoElement(SEARCH_BOX, searchData);
  }
  public void navigatToUrl() {
     driver.get(url);
  }
  public void captureSearchSuggestion(String pathToJsonDataStore, String searchData) {
     List<WebElement> elements = getElements(SUGGESTION_BOX);
     jsonHandler.captureAndWriteJsonData(elements, pathToJsonDataStore, searchData);
  }
  public void genericWait(int timeOuts) {
     implicitlyWait(timeOuts);
  }
  public void clikcOnSelectedElement(String option) {
     int optionSelection = Integer.parseInt(option);
     safeClick(By.xpath("//div[@id='s-separator']/following-sibling::div[" + optionSelection + "]"));
  }
}

Likewise, you can keep on including the page features in the page different Page methods inside the respective page classes. 

Here is how the Page locators interfaces look like : 

package com.page.locatorModules;
import org.openqa.selenium.By;
public interface HomePageLocators {
 
  By SEARCH_BOX=By.id("twotabsearchtextbox");
  By SUGGESTION_BOX=By.xpath("//div[@id='suggestions']/div");
 
}

Now the next segment, you can create a baseSetUp or Basetest where you want to perform the initialization/data loading parts. Also, you could use @beforeTest, @beoforeClass methods in this class itself and use them in your test classes.

BaseSetup Class looks like : 

package com.demo.testS;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.DataProvider;
import com.base.dataUtils.DataHelperProvider;
import com.base.dataUtils.IDataProvider;
import com.base.driverUtils.DriverProvider;
public class BaseSetUp {
\tpublic WebDriver driver;
\tDriverProvider browserProvider = new DriverProvider();
\tDataHelperProvider datahelperProvider = new DataHelperProvider();
\tIDataProvider dataProvider = datahelperProvider.getDataHelperProvider("properties");
\tIDataProvider dataProviderExcel = datahelperProvider.getDataHelperProvider("excel");
\tpublic final String configProperties = "..\\\\DummyAutomation\\\\TestConfigsData\\\\config.properties";
\tpublic String url = dataProvider.fetchData(configProperties, "url");
\tString modeOfExecution = dataProvider.fetchData(configProperties, "modeOfExecution");
\tString browserName = dataProvider.fetchData(configProperties, "browser");
\tString pathToJasonDataStore = "..\\\\DummyAutomation\\\\ProductJsonData\\\\";
\tString pathToExcelData = "..\\\\DummyAutomation\\\\TestConfigsData\\\\TestData.xlsx";
\tpublic WebDriver getDriver() {
\t\treturn driver;
\t}
\tprotected void setDriver() {
\t\tdriver = browserProvider.getDriver(modeOfExecution).init(browserName);
\t}
\t@DataProvider(name = "SearchFunctionality")
\tpublic Object[][] getCityDetails() {
\t\tObject[][] arrayObject = dataProviderExcel.fetchDataSet(pathToExcelData, "DataFeed");
\t\treturn arrayObject;
\t}
}

Test Classes: As we would be using TestNG here, so you need to write @test method for the test script to be developed, such as : 

Here is the code snippet for the Test Classes  

package com.demo.testS;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.base.pageModules.HomePage;
import com.base.pageModules.SearchPage;
public class DemoTest extends BaseSetUp {
  HomePage homePage;
  SearchPage searchPage;
  @BeforeMethod
  public void setUpTest() {
     setDriver();
     homePage = new HomePage(driver);
     searchPage = new SearchPage(driver);
     homePage.navigatToUrl();
  }
  @Test(dataProvider = "SearchFunctionality")
  public void search(String searchData, String selectOption) {
     homePage.enterSearchdataToSearchField(searchData);
     homePage.genericWait(5);
     homePage.captureSearchSuggestion(pathToJasonDataStore, searchData);
     homePage.clikcOnSelectedElement(selectOption);
     searchPage.clickOnFirstProduct();
     searchPage.switchToProductSpecificPage();
     searchPage.captureProductData(pathToJasonDataStore, searchData);
  }
  @AfterMethod
  public void tearDown() {
     if (driver != null) {
        driver.quit();
     }
  }
}

TestNgXML file -Page Object Model framework

You would need to define an XML class for the testng.xml, which basically a unit test framework and controls the flow of your automation; you can mention the test classes there themselves.

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="test-parameter" parallel="tests" thread-count="3">
<test name="DemoAutomation_TarGet">
<classes>
<class name="com.demo.testS.DemoTest"></class>
</classes>
</test>
</suite>

So with these activities, your basic Page Object Model framework should be ready now. If you want to Achieve the advanced version of your framework, then you could incorporate these below areas : 

Reporting Feature-Page Object Model Framework

You can use any reporting feature available like allure, extentreport, TestNG report, or advance reporting by using ELK stack, etc. 

Just to keep the simplicity, we are showing here the reporting feature with Extent report, which is having many features along with it and can be considered as an intermediate level of reporting. 

You have to build a class to have the utilities to work with Extent report, and while doing so, you have to implement the interface ITestlistener from TestNg; the below code shows how : 

package com.cyborg.core.generic.reportUtils;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.cyborg.core.generic.dataUtils.PropertiesDataUtils;
import io.appium.java_client.android.AndroidDriver;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.Augmenter;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.Reporter;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
public class ExtentReportUtils implements ITestListener {
  String screenShotPath = "";
  static ExtentReports extentReports;
  ExtentHtmlReporter extentHtmlReporter;
  protected ExtentTest extentTest;
  static String pathOfFile = "./configurator.properties";
  PropertiesDataUtils propertiesDataUtils = PropertiesDataUtils.getInstance(pathOfFile);
   Boolean log_to_kibana=Boolean.parseBoolean(PropertiesDataUtils.configDataStore.get("log_to_kibana"));
 
   public void setup() {
     try {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        Date now = new Date();
        String currentTime = simpleDateFormat.format(now);
        extentHtmlReporter = new ExtentHtmlReporter(
              new File(System.getProperty("user.dir") + "_Reports_" + currentTime + ".html"));
        extentHtmlReporter.loadXMLConfig(
              new File(System.getProperty("user.dir") + "/src/test/resources/config/extent-config.xml"));
        extentReports = new ExtentReports();
        extentReports.setSystemInfo("Environment", PropertiesDataUtils.configDataStore.get("Environment"));
        extentReports.setSystemInfo("AppName", PropertiesDataUtils.configDataStore.get("AppName"));
        extentReports.setSystemInfo("ModeOfExecution", PropertiesDataUtils.configDataStore.get("modeOfExecution"));
        extentReports.attachReporter(extentHtmlReporter);
        System.out.println("DONE SETUP FOR extent Report");
     } catch (Exception ex) {
        ex.printStackTrace();
     }
  }
  public void setup(String reportName) {
     extentReports = getExtent(reportName);
  }
  public ExtentReports getExtent(String reportName) {
     if (extentReports != null)
        return extentReports; // avoid creating new instance of html file
     extentReports = new ExtentReports();
     extentReports.attachReporter(getHtmlReporter(reportName));
     return extentReports;
  }
  private ExtentHtmlReporter getHtmlReporter(String reportName) {
     extentHtmlReporter = new ExtentHtmlReporter("./reports/" + reportName + ".html");
     extentHtmlReporter.loadXMLConfig("./src/test/resources/config/extent-config.xml");
     // make the charts visible on report open
     extentHtmlReporter.config().setChartVisibilityOnOpen(true);
     extentHtmlReporter.config().setDocumentTitle(PropertiesDataUtils.configDataStore.get("AppName"));
     extentHtmlReporter.config().setReportName("Regression Cycle");
     // Append the existing report
     extentHtmlReporter.setAppendExisting(false);
     Locale.setDefault(Locale.ENGLISH);
     return extentHtmlReporter;
  }
  public void registerTestMethod(Method method) {
     String testName = method.getName();
     extentTest = extentReports.createTest(testName);
  }
  public void sequenceScreenShot(AndroidDriver driver, String application, String step) {
     try {
        extentTest.addScreenCaptureFromPath(screenshotStepWise(driver, application, step));
     } catch (Exception e) {
        e.printStackTrace();
     }
  }
  public void screenshotAnyCase(ITestResult result, WebDriver driver, String application) {
     String testName = result.getName();
     File file = new File(".");
     String filename = testName + ".png";
     String filepath = null;
     try {
        filepath = file.getCanonicalPath() + "/ScreenShots/" + application + "/" + putLogDate() + filename;
     } catch (IOException e1) {
        e1.printStackTrace();
     }
     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        screenShotPath = "job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDate() + filename;
     else
        screenShotPath = System.getProperty("user.dir") + "/ScreenShots/" + application + "/" + putLogDate()
              + filename;
     try {
        WebDriver augmentedDriver = new Augmenter().augment(driver);
        File screenshotFile = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenshotFile, new File(filepath));
        File reportFile = new File(filepath);
        reportLogScreenshot(reportFile, filename, application);
     } catch (Exception e) {
        Reporter.log("Unable to get the screenshot");
     }
  }
  public String screenshotStepWise(WebDriver driver, String application, String step) throws Exception {
     File file = new File(".");
     String filename = step + ".png";
     String filepath = null;
     try {
        filepath = file.getCanonicalPath() + "/ScreenShots/" + application + "/" + putLogDateWithoutmm() + filename;
     } catch (IOException e1) {
        e1.printStackTrace();
     }
     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        screenShotPath = "job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDateWithoutmm() + filename;
     else
        screenShotPath = System.getProperty("user.dir") + "/ScreenShots/" + application + "/"
              + putLogDateWithoutmm() + filename;
     try {
        WebDriver augmentedDriver = new Augmenter().augment(driver);
        File screenshotFile = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenshotFile, new File(filepath));
     } catch (Exception e) {
        Reporter.log("Unable to get the screenshot");
     }
     return screenShotPath;
  }
  protected void reportLogScreenshot(File file, String fileName, String application) {
     System.setProperty("org.uncommons.reportng.escape-output", "false");
     String absolute = file.getAbsolutePath();
     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        absolute = " /job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDate() + fileName;
     else
        absolute = System.getProperty("user.dir") + "/ScreenShots/" + application + "/" + putLogDate() + fileName;
     screenShotPath = absolute;
  }
  public void captureStatus(ITestResult result) {
     if (result.getStatus() == ITestResult.SUCCESS) {
        extentTest.log(Status.PASS, "The test method Named as :" + result.getName() + " is PASSED");
        try {
           extentTest.addScreenCaptureFromPath(screenShotPath);
        } catch (IOException e) {
           e.printStackTrace();
        }
     } else if (result.getStatus() == ITestResult.FAILURE) {
        extentTest.log(Status.FAIL, "The test method Named as :" + result.getName() + " is FAILED");
        extentTest.log(Status.FAIL, "The failure : " + result.getThrowable());
        extentTest.log(Status.FAIL, "StackTrace: " + result.getThrowable());
        try {
           extentTest.addScreenCaptureFromPath(screenShotPath);
        } catch (IOException e) {
           e.printStackTrace();
        }
     } else if (result.getStatus() == ITestResult.SKIP) {
        extentTest.log(Status.SKIP, "The test method Named as :" + result.getName() + " is SKIPPED");
     }
  }
  public String putLogDate() {
     Calendar c = new GregorianCalendar();
     c.add(Calendar.DATE, +0);
     Date s = c.getTime();
     String dateString = new SimpleDateFormat("_EEE_ddMMMyyyy_hhmm").format(s);
     return dateString;
  }
  public String putLogDateWithoutmm() {
     Calendar c = new GregorianCalendar();
     c.add(Calendar.DATE, +0);
     Date s = c.getTime();
     String dateString = new SimpleDateFormat("_EEE_ddMMMyyyy_hh").format(s);
     return dateString;
  }
  public void cleanup() {
     extentReports.flush();
  }
  public void onTestStart(ITestResult result) {
     /*
      * try { DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH-mm-ss"); Date
      * date = new Date();
      */
     /*
      * record = new ATUTestRecorder(System.getProperty("user.dir")+"/videos",
      * dateFormat.format(date), false); record.start();
      *//*
         *
         * } catch (ATUTestRecorderException e) { e.printStackTrace(); }
         */
  }
  public void onTestSuccess(ITestResult result) {
     /*
      * try { record.stop(); } catch (Exception e) { e.printStackTrace(); }
      */
     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testDescription.split("_")[1];
     String status = "PASSED";
     String exceptionType = "NA";
     String detailedError = "NA";
    
     String data ="{\
" +
           "   \\"testCaseNumber\\" : \\""+testCaseNumber+"\\",\
" +
           "   \\"status\\" : \\""+status+"\\",\
" +
           "   \\"testDescription\\" : \\""+testDesc+"\\",\
" +
           "   \\"exceptionType\\" : \\""+exceptionType+"\\",\
" +
           "   \\"detailedError\\":\\""+detailedError+"\\"\
" +
           "   \
" +
           "}";
     
  }
  @Override
  public void onTestFailure(ITestResult result) {
    
     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testCaseNumber.split("_")[1];
     String status = "FAILED";
     String exceptionType = String.valueOf(result.getThrowable().getClass().getSimpleName());
     String detailedError = String.valueOf(result.getThrowable().getMessage());
    
     String data ="{\
" +
           "   \\"testCaseNumber\\" : \\""+testCaseNumber+"\\",\
" +
           "   \\"status\\" : \\""+status+"\\",\
" +
           "   \\"testDescription\\" : \\""+testDesc+"\\",\
" +
           "   \\"exceptionType\\" : \\""+exceptionType+"\\",\
" +
           "   \\"detailedError\\":\\""+detailedError+"\\"\
" +
           "   \
" +
           "}";
    
     // TODO Auto-generated method stub
  }
  @Override
  public void onTestSkipped(ITestResult result) {
     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testCaseNumber.split("_")[1];
     String status = "SKIPPED";
     String exceptionType = result.getThrowable().getClass().getSimpleName();
     String detailedError = result.getThrowable().getMessage();
    
     String data ="{\
" +
           "   \\"testCaseNumber\\" : \\""+testCaseNumber+"\\",\
" +
           "   \\"status\\" : \\""+status+"\\",\
" +
           "   \\"testDescription\\" : \\""+testDesc+"\\",\
" +
           "   \\"exceptionType\\" : \\""+exceptionType+"\\",\
" +
           "   \\"detailedError\\":\\""+detailedError+"\\"\
" +
           "   \
" +
           "}";
  }
  @Override
  public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
     // TODO Auto-generated method stub
  }
  @Override
  public void onStart(ITestContext context) {
     // TODO Auto-generated method stub
  }
  @Override
  public void onFinish(ITestContext context) {
     // TODO Auto-generated method stub
  }
}

Conclusion : With this we are concluding the Selenium Page Object Model framework development through which you can start building the Page Object model framework and can take it to the advanced level , in the upcoming series of the tutorial we will discuss more on the advanced features of Selenium framework . To go through the series of Selenium tutorial you can go through here .

2 Important Selenium design patterns and best practices

selenium design patterns and best practices 0

In this tutorial we will learn about Selenium design patterns and best practices while working with Selenium Automation framework development (hybrid framework in selenium), there two variations of Framework Design or Framework model that we have to consider, which are : 

We need to know and understand why Language design pattern is required when we are developing our framework in one of the Selenium framework Model. We would suggest to go through the previous segments of the Selenium Framework development tutorial series to get the whole understanding .

Let’s understand that in detail: 

selenium design patterns and best practiceshybrid framework in selenium

While designing any Framework, we need to consider some design architecture, i.e., selenium design patterns and best practices, and as per the need of the type of the framework model, we need to select a Language Design pattern to solve the problem state of the framework design as a whole.

Hence just to conclude, we can choose and Selenium framework model (Hybrid, Page Object Model, Data Driven, etc.), but to implement the model, we need to follow and implement some Language Design Pattern(e.g., java/C# Design patterns ) 

Why We need selenium design Pattern and best practices while building Selenium Framework: 

What design patterns to be used in Selenium Framework : 

There are a few design pattern you could use to implement different areas of the framework, such as an example : 

We will do the live coding template of the whole Framework in the upcoming posts here.

Singleton Design Pattern for hybrid framework in Selenium: 

Singleton Design Pattern is a pattern in which you could create only one object from a class and get to use the same object to access the methods of the class; we could use the design pattern in the configurator where we only need to read the configuration data and can load into some data store(any kind of data structure which you could use as and when required while in the execution from any classes and methods ) 

So we could achieve the same in the below manner while designing the same with Singleton Design pattern. 

NOTE: We will design and develop the framework from scratch in the upcoming section of the tutorial series, but this specific tutorial will provide you insight into the necessity of the design pattern.

package com.cyborg.core.generic.dataUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Set;
import org.apache.log4j.PropertyConfigurator;
// This is the SingleTon Class 
public class PropertiesDataUtils {
   private Properties properties = null;
   public static LinkedHashMap<String, String> configDataStore = new LinkedHashMap<String, String>();
   InputStream is = null;
// This is the static and private reference of the class which you could use anywhere in you framework 
   private static PropertiesDataUtils propertiesDataUtils = null;
   boolean centralizeLog  = false;
// This is the Private constructor to create the object but you can not access this from outside the class to maintain the design of the SingleTon pattern ie only one object creation .
   private PropertiesDataUtils(String filePath) {
       generateDataStore(filePath);
       centralizeLog =  Boolean.parseBoolean(PropertiesDataUtils.configDataStore.get("centralizedLog"));
       if(centralizeLog)
           PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_central.properties");
         else
            PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_local.properties");
   }
   private PropertiesDataUtils() {
   }
  
 
// This method basically create the instance of the SingleTon class 
   public static PropertiesDataUtils getInstance(String filePath) {
       if (propertiesDataUtils == null)
           propertiesDataUtils = new PropertiesDataUtils(filePath);
       return propertiesDataUtils;
   }
// this method basically creates the datastore where you want to store all the config data as discussed previously 
   private void generateDataStore(String filePath) {
       try {
           this.properties = new Properties();
           is=new FileInputStream(filePath);
           properties.load(is);
           overrideFromEnvironment();
           Set<Object> keys = loadAllKeys();
           for (Object k : keys) {
               String key = (String) k;
               configDataStore.put(key, getPropertyValue(key));
           }
       } catch (FileNotFoundException fileNotFoundException) {
           String exceptionData = String.valueOf(fileNotFoundException.getCause().getMessage());
       } catch (IOException ioException) {
           String exceptionData = String.valueOf(ioException.getCause().getMessage());
       } finally {
           if (null != is) {
               try {
                   is.close();
               } catch (Exception e) {
                   String exceptionData = String.valueOf(e.getCause().getMessage());
               }
           }
       }
   }
// This method is used to load all the keys from the properties file.
   private Set<Object> loadAllKeys() {
       Set<Object> keys = this.properties.keySet();
       return keys;
   }
   private String getPropertyValue(String key) {
       return this.properties.getProperty(key);
   }
   private void setPropertyValue(String key,String value) {
        this.properties.setProperty(key,value);
   }
  
  private void overrideFromEnvironment() {
     if (this.properties.getProperty("run_on_jenkins").equals("true")) {
        System.out.println("SET run_on_jenkins FLAG TO FALSE IN YOUR PROPERTIES FILE TO RUN LOCALLY....");
        String build_number = System.getenv("BUILD_NUMBER");
        this.properties.setProperty("build_number", build_number);
     }
    
  }
}

By this approach, we could use the Singleton design pattern and use it in our framework.

Factory Design Pattern in Selenium Framework : 

In the factory design pattern, we create a class (we call it a Factory class ), and on the other hand, we have one interface and eventually implemented by “n” number of classes.

The factory class basically returns the object of the above classes (depending on the need), so you don’t have to deal with the above “n” number of classes’ object; rather, you can create one object of the Factory class and call the method of factory class which returns the needed baseline Object for the required classes among the adobe “n” classes.

Now, this design you can consider while creating the different Webdriver / browser implementation. 

We have a various browser and the implementation with a different type of Selenium driver (e.g., LocalDriver, RemoteDriver, ThreadDriver, etc.) and as and when you require a specific type of driver and specific type of browser you can mention in the configuration file and based on the need the factory class will provide you the instance of the driver and browser for your automation script to use further. 

Here is the code base for implementing this design pattern while creating driver -browser interactions : 

Interface Design : 

package com.cyborg.core.web.utils.driverUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public interface IDriver {
   public WebDriver init(String browserName);
}

“N” number of browse classes implementation (who are implementing the interface ) :

package com.cyborg.core.web.utils.driverUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.safari.SafariDriver;
public class LocalDriver implements IDriver {
   public WebDriver init(String browserName) {
       String pathToDriver = getDriverPath(browserName);
       if (null != browserName) {
           switch (browserName) {
               case "chrome":
                   System.setProperty("webdriver.chrome.driver",
                           pathToDriver);
                   return new ChromeDriver();
               case "firefox":
                   System.setProperty("webdriver.gecko.driver", pathToDriver);
                   return new FirefoxDriver();
               default:
                   System.setProperty("webdriver.chrome.driver", pathToDriver);
                   return new ChromeDriver();
           }
       } else {
           System.setProperty("webdriver.chrome.driver",
                   pathToDriver);
           return new ChromeDriver();
       }
   }
   private String getDriverPath(String browserName) {
       String osData = System.getProperty("os.name").toLowerCase().split("\\\\s")[0];
       if (null != osData) {
           if (osData.equalsIgnoreCase("mac")) {
               return "./DriversExe/" + osData + "_" + browserName;
           } else if (osData.contains("nux") || (osData.contains("nix"))) {
               return "./DriversExe/linux_" + browserName;
           } else if (osData.contains("win")) {
               return "./DriversExe/" + osData + "_" + browserName + ".exe";
           }
       }
       return null;
   }
}

Here is the implementation of the Remote Driver class : 

package com.cyborg.core.web.utils.driverUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import com.cyborg.core.generic.dataUtils.PropertiesDataUtils;
import java.net.MalformedURLException;
import java.net.URL;
public class RemoteDriver implements IDriver {
   DesiredCapabilities caps;
   String remoteHuburl=PropertiesDataUtils.configDataStore.get("WEB_GRID_IP");
   @Override
   public WebDriver init(String browserName) {
       if (browserName != null) {
           switch (browserName) {
               case "firefox":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
                   } catch (MalformedURLException malformedUrlEx) {
                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
               case "chrome":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
                   } catch (MalformedURLException malformedUrlEx) {
                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
               case "ie":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.internetExplorer());
                   } catch (MalformedURLException malformedUrlEx) {
                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
               default:
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
                   } catch (MalformedURLException malformedUrlEx) {
                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
           }
           return null;
       } else {
           return null;
       }
   }

Here is the implementation of the Factory class, which provides the respective browser and driver class object : 

package com.cyborg.core.web.utils.driverUtils;
public class DriverProvider {
   public IDriver getDriver(String typeOfDriver) {
       if (typeOfDriver != null) {
           switch (typeOfDriver) {
               case "local":
                   return new LocalDriver();
               case "remote":
                   return new RemoteDriver();
              
               default:
                   return new LocalDriver();
           }
       } else {
           return null;
       }
   }
}

Likewise, you can implement the Appium driver along with the same design, just provide the implementation and declare a method in the IDriver interfaces. 

Conclusion: With this, we are concluding here how you can use language design patterns as part of the Selenium design patterns and best practices while developing the hybrid framework in Selenium; in the upcoming segments of the tutorial, we will build the Page Object model framework for Selenium Automation.

To get the Overall tutorial on Selenium, you can visit here

Expert Level Selenium Framework 2021

In this tutorial, we will learn exhaustively about the Test Automation framework and design and develop the Selenium framework from scratch to the advanced level.

Let’s break this series of tutorials into multiple modules to accomplish the Selenium Framework Development with Java from concept to advanced level.

Types of the Selenium Framework and their Features

Different types of Selenium Framework are designed and built considering the Application needs that you want to automate. Every different type of test Automation framework is having different features and advantages/disadvantages.

We can classify the Selenium Framework in the below areas :

Test Automation Selenium Framework Features

Keyword Driven Framework in Selenium

What is keyword driven framework?

Keyword Driven Framework in selenium is a Selenium framework built around the feature or design where the Keyword drives the framework; we will see how. 

How Keyword Driven framework Works : 

As mentioned above, KDF is dependent or designed based on Keywords, So what is a keyword? 

Keywords are nothing but the web action words (like click, type, mouseHover, switchFrame etc. ), now you store these keywords in Some repo (or let’s say in Excel files) and for all the keyword’s actions you define a class (which is WebAction utility using Selenium commands ) and write specific methods for Specific Keywords.

Now the next step is basically from your script when you mention let’s say click on some webelement then, in that case, the respective operation goes to the Keyword’s repo (here in our case Excel and then depending on the operation it calls the respective methods which you had defined in the class ).

Additionally, You have different reporting mechanisms (let’s say reportNg or Allure report ) which you can integrate with your Selenium framework to take care of the reporting.

keyword driven framework advantages

keyword driven framework disadvantages 

Data driven framework in Selenium 

What is Data driven framework?

Data Driven framework in selenium is a type of Selenium framework which is built around the feature or design where the data drives the framework; we will see how :

How Data Driven framework Works

Data Driven Framework is designed to handle complex and various type of Data to perform the Automation of the application.

This kind of framework is useful and built where your automation scenarios and use cases must be tested with various sets of data on the same functionalities.

So Data drives the flow of Automation where same test scenarios are tested with respect to different data sets, and DDF should be able to handle various types of Data such as Excel, CSV, YML, PDF, Text, DataBase, Image Data etc.

So you can use TestNG data provider, TestNG XML parameterized Data, JDBC connection manager, PDF data handler, YML data handler. 

You can use Tesseract OCR for working with image data handling.

Data driven framework advantages 

Data driven framework disadvantages

 

Hybrid framework in Selenium Automation

What is Hybrid framework?

Hybrid framework in selenium is a type of Selenium framework which basically is built around the feature or design by taking the concept of both Keyword driven and Data driven framework. 

So, 

Hybrid Framework => Data Driven Framework + Keyword Driven framework.

How Hybrid Framework Works

The hybrid framework supported and driven by Keyword Driven approach with the capability to handle Data driven testing, so both the features are enabled with Keywords repository and their implementation and along with Various Data providers and Dala handlers which is the core feature of the Data Driven Framework.

Page Object Model – Test Automation framework

What is Page Object Model 

Page Object Model framework as the name suggests, is basically a Selenium framework design and developed around the below features and concepts :

Why Page Object Model || Advantages of a page object model

Page Object Model framework design is one of the latest framework model used in the industry, and it comes up with various advance features along with it  

We will see how to design the exhaustive Page Object Model framework here.

Hybrid Page Object Model Selenium framework

Hybrid Page Object Model framework is designed with an approach where its the combination of Data driven Framework and Page Object Model framework.

Here in the Hybrid Page Object Model framework, the Core Design is based on the Page Object model and uses the vast data handler to work with Data-Driven Testing.

We will Design the Hybrid Page Object model Framework here. 

Behavior driven development (BDD) Test Automation framework 

BDD framework is a Selenium framework where the design and the flow of Automation are driven by the behaviour.

What is BDD framework? 

BDD framework is controlled or designed based on the behaviour of the test cases or actions performed. 

In BDD framework, we use English like language called Gherkin language, which is the driving point of the framework. 

Gherkin language is basically in the format of given, when, then (where given narrates a precondition when means when you perform some operation on some webelement like let’s say click operation etc. and then is basically for assertion )

Tools and Technologies required for the Automation Framework

Selenium is an open-source tool, and it does not provide any inbuilt framework along with. Hence you need to design and develop the Selenium framework along with Tools and technologies. 

You could use the tools to work with Selenium framework Development

These are the majorly and frequently used Tools and tech stack to build a robust Selenium framework. 

Conclusion: This tutorial We had an overview of the Selenium Automation framework and what are features of a Selenium framework and what tools are required to build a Robust Test Automation Framework, in the upcoming tutorials we will discuss about the Design Principles and design patterns to build a Selenium framework and eventually we will end up creating a framework hands on which you could use at your own approach. To learn about the whole Selenium tutorial you can visit here and for Critical Selenium Interview Questions click here.

Critical 12 javascriptexecutor methods in selenium

JS Executor 724x1024 1

In this segment of the tutorial we are going to discuss javascriptexecutor in selenium in detailed manner and all the probable operations could be performed using javascriptexecutor in selenium in terms of WebAutomation . 

What is javascriptexecutor in selenium 

In the Selenium Library javascriptexecutor is an interface which is being implemented several classes such as ChromeDriver,FirefoxDriver, RemoteWebDriver,EdgeDriver, EventFiringWebDriver, InternetExplorerDriver etc. to support different Javascript related operations towards the respective browser Drivers.

JavaScriptExecutor in Selenium
JavaScript Executor in Selenium

Types of Java Script in Selenium and its Methods: 

There are two different kinds of JavaScript methods are available : 

Difference between executeAsyncScript vs executeScript :

executeAsyncScript  : This type of java script executor is used to execute an asynchronous JavaScript code in the context of the currently selected frame or window.

executeScript : This type of the Java scriptexecutor which basically executes synchronous JavaScript code in the context of the currently selected frame or window. 

 

Operation That could be performed using  javascript executor in selenium : 

There are various crucial Web operations that is achieved executing Javascript in browser driver to achieve certain operation such as : 

Lets discuss all the operation mentioned above : 

Selenium javascript click 

We can perform click operation in Selenium with Javascript operation in the below approach : 

public void jsClick() {
   WebElement element = driver.findElement(By.xpath("Xpath_OF_Element"));
   JavascriptExecutor jscriptExecutor = (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("arguments[0].click();", element);
}

Selenium javascript enter text

We can perform sendkeys operation in Selenium with Javascript operation in the below approach : 

public void jsSendKeys() {
   JavascriptExecutor jscriptExecutor = (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("document.getElementById('id_of_the_element').value='ENTER_THE_TEXT_HERE';");
}

Selenium javascript check checkbox 

We could use option checked=true or false depending on the use-cases to perform the CheckBox operations with Javascript in Selenium.

public void jsCheckBoxOps() {
   JavascriptExecutor jscriptExecutor = (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("document.getElementById('id_of_the_element').checked=false;");
}

Selenium javascript Alert generation

To generate the alert we need to use “alert(‘ALERT_TEXT_TO_BE_SHOWN’);” while performing the operation with Javascript.

public void jsAlertGeneration() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("alert('ALERT_TEXT_TO_BE_SHOWN');");
}

Selenium javascript refresh page

To refresh a webpage in Selenium with Javascript Executor we can use history.go(0).

public void jsRefreshPage() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("history.go(0)");
}

Selenium javascript to get  inner text of WebPage

To fetch the whole inner text we can use document.documentElement.innerText;

public String jsFetchInnerText() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   return String.valueOf(jscriptExecutor.executeScript("return document.documentElement.innerText;"));
}

Selenium javascript get title of the Page 

To return the title of a Page we can use document.title; along with Javascript Executor in Selenium .

public String jsWebPageTitle() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   return String.valueOf(jscriptExecutor.executeScript("return document.title;"));
}

Selenium javascript to get the Domain 

To pull the domain name we can use document.domain;

public String jsFetchDomain() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   return String.valueOf(jscriptExecutor.executeScript("return document.domain;"));
}

Selenium javascript to get the URL of a webpage

 

To fetch the URL using JavaScript Executor with Selenium we could use document.URL;

public String jsFetchURL() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   return String.valueOf(jscriptExecutor.executeScript("return document.URL;"));
}

Selenium javascript Scrolling a webpage 

We can perform scrolling is multiple ways using Javascript , two of the approaches are shown below in the code snippet such as :

public void scrollIntoView(By locator) {
   try {
       JavascriptExecutor executor = (JavascriptExecutor) driver;
       WebElement element = driver.findElement(locator);
       executor.executeScript("arguments[0].scrollIntoView(true);", element);
       BASE_LOGGER
               .info("scrollIntoView operation has been performed for the locator : " + String.valueOf(element));
   } catch (Exception e) {
       String exceptionData = e.getCause().getMessage();
       BASE_LOGGER.error("Error encountered i.e : " + exceptionData
               + " while performing scrollIntoView on the element : " + locator);
   }
}

Also we can specify the scrolling value(amount of scroll) like this below approach :

public void jsScroll() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("window.scrollBy(0,1000)");
}

Selenium javascript to navigate to a different page

We can navigate to a different webpage/screen by directly providing the url location within the javascriptexecutor in Selenium. 

public void pageNavigationWithJS() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   jscriptExecutor.executeScript("window.location = 'PageURL_To_Navigate'");
}

Selenium javascript To find and click on a hidden element

We could directly click on the hidden element with the Javascript from the backend even though the element is not visible , here is the code snippet for the same:

public void clickOnHiddenElement() {
   JavascriptExecutor jscriptExecutor= (JavascriptExecutor) driver;
   WebElement hiddenElement=driver.findElement(By.id("ID_OF_ELEMENT"));
   jscriptExecutor.executeScript("arguments[0].click();", hiddenElement);
}

Conclusion :

We have so far discussed about the Javascript and various operations to be performed using Javascript executor in Selenium , you are encouraged to go through the full Selenium tutorial to get a better grip on all the different aspects of the same. In the upcoming Segments of Tutorial series we will discuss more on the Selenium Automation Framework and other latest technologies to work with Selenium , and to crack any advanced interview in Selenium you can go through here.

Critical Actions class in selenium -Absolute 2021 guide

Actions Class Selenium 212x300 1

We are going to discuss and learn exhaustive usage of Actions class in Selenium across different Web operations . Actions Class in Selenium is widely used to perform various web operations such as mouse and keyboard movement which are advance webbrowser actions.

Mouse Actions

Keyboard Actions

Actions class in selenium

What is Actions Class in Selenium : 

Actions class in selenium
Actions class in Selenium

Actions Class is a class from Selenium Bundle Api from the package org.openqa.selenium.interactions to handle Critical and advance Web interactions with Users through browser Automation. Provides users with a handle to perform various Mouse and Keyboard Actions via different methods mentioned above.  

Actions class in selenium
Actions class in Selenium

We will discuss here all the Web interactions via Actions Class in Selenium, to start with We learn the Mouse Interactions and move towards KeyBoard Interactions with Actions class in Selenium.

Mouse Interactions – Actions Class in Selenium

Drag and drop in selenium

Drag and Drop in Selenium can be done in three different approaches with Actions class in Selenium : 

Drag and Drop in Selenium with Action Class in Selenium via build method : 

We need to have two webelements to perform Drag and Drop in Selenium such as Source WebElement (which is to be dragged) and Destination WebElement (Where the Source WebElement to be dropped, i.e. the Destination WebElement ), The below method is a customized method (which you could use to build your Framework WebUtils) which perform the Drag And Drop in Selenium and this method takes two arguments one is Source WebElement, and another one is Destination WebElement as mentioned previously: 

public void dragAndDrop(By source, By destination) {
   try {
       WebElement sourceElement = driver.findElement(source);
       WebElement destinationElement = driver.findElement(destination);
       Actions builder = new Actions(driver);
       Action dragAndDrop = builder.clickAndHold(sourceElement).moveToElement(destinationElement)
               .release(destinationElement).build();
       dragAndDrop.perform();
       BASE_LOGGER.info("Successfully performed the Drag and Drop action ");
   } catch (Exception e) {
       String exceptionData = e.getCause().getMessage();
       BASE_LOGGER.error("Error encountered i.e : " + exceptionData + " while performing DragAndDrop ");
   }
}

To learn the whole concept about drag and drop and get to all the approaches to perform Drag and Drop in Selenium, click here.

ClickAndHold in Selenium 

ClickAndHold is another important method from the Actions class (from org.openqa.selenium.interactions package) in Selenium to
first perform left click operation over any webElement and hold it without releasing mouse.

This method is majorly used while performing the drag and drop scenarios, below is the sample code image : 

Actions class in selenium
click and hold -Actions class in Selenium

MoveToElement in Selenium

MoveToElement is a method from the Actions class in Selenium to perform the movement to another WebElement (Destination Webelement), which this method takes as one respective argument.

This method is majorly used while performing the drag and drop scenarios, below is the sample code image : 

MoveToElement
Move to element – Actions class in Selenium

Double Click in Selenium

To replicate the double click operation via mouse we need to Perform double click via Actions class in Selenium and we can do it in the below approach : 

public void doubleClick(By locator) {
   try {
       WebElement element = driver.findElement(locator);
       Actions actions = new Actions(driver);
       actions.doubleClick(element).perform();
       BASE_LOGGER.info("Performed the double Click on the Element  : " + locator);
   } catch (StaleElementReferenceException e) {
       BASE_LOGGER.error("Element is not attached to the page document " + e.getCause().getMessage());
   } catch (NoSuchElementException e) {
       BASE_LOGGER.error("Element " + locator + " was not found in DOM " + e.getCause().getMessage());
   } catch (Exception e) {
       BASE_LOGGER.error("Element " + locator + " was not clickable " + e.getCause().getMessage());
   }
}

The above code snippet is a method which basically takes an argument as Locator, i.e. the WebElement on which the double click has to be performed. 

context click or Selenium right click

To replicate the context click or right click operation via mouse we need to Perform context click method via Actions class in Selenium and we can do it in the below approach : 

public void rightClick(By locator) {
   try {
       WebElement element = driver.findElement(locator);
       Actions actions = new Actions(driver);
       actions.contextClick(element).perform();
       BASE_LOGGER.info("Performed the context Click on the Element  : " + locator);
   } catch (StaleElementReferenceException e) {
       BASE_LOGGER.error("Element is not attached to the page document " + e.getCause().getMessage());
   } catch (NoSuchElementException e) {
       BASE_LOGGER.error("Element " + locator + " was not found in DOM " + e.getCause().getMessage());
   } catch (Exception e) {
       BASE_LOGGER.error("Element " + locator + " was not clickable " + e.getCause().getMessage());
   }
}

The above code snippet is a method which basically takes an argument as Locator, i.e. the WebElement on which the double click has to be performed. 

Pause in Selenium 

Whenever we want to have introduced any time delay between different Actions we could use the pause method in between the Actions operations, like let’s say if we want to have some few seconds of delay between drag and drop operation, then we can call the pause() method of Actions Class in Selenium in below approach : 

public void pauseBetweenActions(By source,By destination, int timeUnit) {
   try {
       WebElement sourceElement = driver.findElement(source);
       WebElement destinationElement = driver.findElement(destination);
       Actions builder = new Actions(driver);
       builder.clickAndHold(sourceElement).moveToElement(destinationElement).pause(timeUnit).release(destinationElement).build().perform();
       BASE_LOGGER.info("Successfully performed the Drag and Drop action ");
   } catch (Exception e) {
       String exceptionData = e.getCause().getMessage();
       BASE_LOGGER.error("Error encountered i.e : " + exceptionData + " while performing DragAndDrop ");
   }
}

In the above method it takes three arguments: one source WebElement, another argument is destination element, and the last one is for timeUnit, i.e. the time delay we want to introduce using the pause() in Selenium.

Mouse hover in selenium

Mouse Hover in Selenium operation can be achieved by using Actions class in Selenium, basically, once we are in focus with any webElement and from there, we want to hover your mouse cursor to any other element by this Mouse Hover operation, and this WebElement where we want to take our mouse cursor is called as Target WebElement. 

Below is the code snippet for the same : 

public void mouseHover(By targetedLocator) {
   try {
       WebElement targetedElement = driver.findElement(targetedLocator);
       Actions builder = new Actions(driver);
       builder.moveToElement(targetedElement).build().perform();
       BASE_LOGGER.info("Successfully performed the Mouse hover in Selenium action ");
   } catch (Exception e) {
       String exceptionData = e.getCause().getMessage();
       BASE_LOGGER.error("Error encountered i.e : " + exceptionData + " while performing Mouse hover in Selenium ");
   }
}

To learn about all the Selenium webdriver command you can refer here .

Keyboard Actions – Actions Class in Selenium

What is Keyboard actions and where its required :

Keyboard actions means where the operations are directly performed from a keyboard such as lets say we are trying to perform Contrl+A together or Control+C together or performing Key up or Keydown button from keyboard while interacting with WebElements .

We can perform several Keyboard interactions with the help of Actions class in Selenium

sendKeys in Selenium :

We can perform sendKeys operation with the help of Actions class in Selenium in the below manner :

public void sendKeysWithActionClass(By locator) {
        try {
            WebElement element = driver.findElement(locator);
            Actions actions = new Actions(driver);
            actions.sendKeys("KeyBoard Data Entry ");
            // Perform Keyboard Actions ex pressing Control and c together
            actions.sendKeys(Keys.CONTROL);
            actions.sendKeys("c");
            actions.build().perform();
        } catch (Exception e) {
            String exceptionData = e.getCause().getMessage();
           
        }
    }

KeyUp in Selenium :

Similarly we can perform KeyUp operations with the Actions class in Selenium in the below manner :

    public void keyUpWithActionClass(By locator) {
        try {
            WebElement element = driver.findElement(locator);
            Actions actions = new Actions(driver);
            actions.sendKeys("KeyBoard Data Entry ");
            // Perform Keyboard Actions ex pressing Control and c together with keyUp
            actions.keyUp(Keys.CONTROL);
            actions.sendKeys("c");
            actions.build().perform();
        } catch (Exception e) {
            String exceptionData = e.getCause().getMessage();
        }
    }

KeyDown in Selenium

We can perform the keyDown operation with the help of again Actions class in Selenium in the below approach :

public void keyDownWithActionClass(By locator) {
        try {
            WebElement element = driver.findElement(locator);
            Actions actions = new Actions(driver);
            actions.sendKeys("KeyBoard Data Entry ");
            // Perform Keyboard Actions ex pressing Control and V together with keyDown
            actions.keyDown(Keys.CONTROL);
            actions.sendKeys("v");
            actions.build().perform();
        } catch (Exception e) {
            String exceptionData = e.getCause().getMessage();
        }
    }

Conclusion: With these we are done here with the Actions class in Selenium ,In the upcoming tutorial JavascriptExecutor in Selenium in modular yet exhaustive manner . To learn Exhaustively the Selenium command you can refer here also to prepare for Critical Selenium interview questions you can refer here .