Automation Framework using Selenium from scratch


Selenium is a free automation testing suite of tools used for only testing web applications. There are many tools available for testing desktop and mobile applications, such as IBM’s RFI, HP’s QPI, Appium, etc. However, the aim of this blog is to make you understand the testing of dynamic web applications and how to define a framework for it.

A framework is a collection of reusable components that makes automation development, execution, and modification easier and faster.


Selenium Automation Testing

Components/Library Used:

  1. Common Utils
  2. POM/Object Repository
  3. Test Data
  4. Resource
  5. Test Scripts
  6. Run Me/driver/XML file
  7. HTML Report
  8. Screen Shots
  9. Maven
  10. Jenkins
  • 1. Common Utils

    It is one of the common components in this framework which can be used in any project. It contains several reusable classes like.

    • A. Base class :
    • It contains common TestNG configuration annotations which are required for all the test scripts. We should extend a base class to use those annotations.

        Usage of TestNG annotations:

      • @Before suite: It is used to configure database connectivity and extend reports and will execute before the <test> tag in an XML file.
      • @Before test: It is used to launch the browser in case of parallel execution before executing each <test> tag in an XML file.
      • @Before Class: It is used to launch the browser in sequential execution and will get executed before executing each class
      • @Before Method: It is used to login into the application which is executed before executing every @test method
      • @After method: It is used to logout from an application which is executed after executing every @test method
      • @After Class: It is used to close the browser in sequential execution and will get executed after executing each class
      • @After suite: It is used to close the database connectivity.
                    package com.automation.blog.geniricutility;
                                             import  org.openqa.selenium.WebDriver;
                    
                  

      Example

                  
                  *Class contains Base Class Specific libraries which Precondition and Post Condition.
      
                  @author author name
                  public   class BaseClass {
      
                    public WebDriver driver = null;
      
                    public static WebDriver sdriver;
      
                    //Object creation for Generic Utility class
      
                    FileUtility flib  = new FileUtility( );
      
                    ExcelUtility elib = new ExcelUtility( );
      
                    JavaUtility jlib = new JavaUtility( );
      
                    WebDriverUtility wlib = new WebDriverUtility( );
      
                    //Before Class annotations is used for lunching the browser
      
                    @BeforeClass
      
                    public void lunchBrowser( )throws Throwable {
      
                    String browser = flib.getPropertyKeyValue("Browser");
      
                    String url = flib.getPropertyKeyValue("Url");
      
                    WebDriverManager.chromedriver( ).setup( );
      
                    if (browser.equalsIgnoreCase("Chrome")) {
      
                    ChromeOptions options = new ChromeOptions( );
      
                        options.addArguments("no-sandbox");
      
                    options.setAcceptInsecureCerts(true);
      
                    driver=new ChromeDriver(options);
      
                    driver.manage( ).window( ).maximize( );
                    }
      
                    else if(browser.equalsIgnoreCase("Firefox")) {
                    driver = new FirefoxDriver( );
                    WebDriverManager.chromedriver().setup( );
                    }
      
                    else {
                    System.out.println("=====Invalid Browser=====");
                    }
      
                    wlib.waitForPageToLoad(driver);
      
                    wlib.maximizeWindow(driver);
      
                    driver.get(url);
      
                    sdriver=driver;
      
                    String userNAME = flib.getPropertyKeyValue("Username");
      
                    String passWORD = flib.getPropertyKeyValue("Password");
      
                    LoginWithGooglePage lg = new LoginWithGooglePage(driver);
      
                    lg.loginWithGmail(userNAME, passWORD);
      
                    wlib.printToConsole("======Login SuccessFull=====");
      
                  }
               
               
    • B. Java Utils:

      It contains java specific methods which can be used for all the test scripts like get-Random-number, get-Date, etc.

    • Example

                  
                    package com.automation.blog.geniricutility;
      
                    import java.sql.Date;
      
                    import java.util.Random;
      
                    import org.apache.commons.lang3.RandomStringUtils;
      
                    Class contains Java Specific libraries which include get System Date & get Random Number etc.
      
                  @author author name
      
                  public class JavaUtility {
      
                      /**
      
                      * Its generate random number with in the limit of 100
      
                      * @return
      
                      */
      
                      public int getRandomNumber() {
      
                      Random ran = new Random();
      
                      int intRandomNum = ran.nextInt(100);
      
                      return intRandomNum;
      
                      }
      
                      /**
      
                      * Its generate Date and Time
      
                      */
      
                      public String getDateAndTime() {
      
                      Date dateObj = new Date(0);
      
                      return dateObj.toString().replace(":", "-").replace(" ", "-");
      
                      }
               
                
    • C. WebDriver Utils:

      It contains web-drivers action which is common for all the test scripts like select, switch-To-Window, switch-To-Frame, etc.

    • Example

                  
                    package com.automation.blog.geniricutility;
               
                    import java.awt.AWTException;
      
                    /**
      
                    * Class contains WebDriver Specific libraries which includes Waiting Condition, Window Switching, Frame Switching, Select class and Actions Class.
      
                  * @author  author name
      
                  public class WebDriverUtility {
      
                    WebDriver driver;
      
                    JsonUtility jsonlib = new JsonUtility();
      
                        /**
      
                        * Wait for page to load before identifying any synchronized element in DOM [HTML document ]
      
                         * @throws ParseException
      
                         * @throws IOException
      
                        */
      
                        public void waitForPageToLoad(WebDriver driver) 
                        throws IOException, ParseException {
      
                    try {
      
                    driver.manage().timeouts().implicitlyWait(jsonlib.getValueFromJSONConfig("implicitlyWait_TimeOut"),TimeUnit.SECONDS);
      
                    } catch (IOException | ParseException e) {
      
                    e.printStackTrace();
      
                    }
      
                    }
      
                    /**
      
                     * Used to wait for element to be clickable in GUI, & check for specific element
                      for every 500 milli seconds
      
                     * @throws ParseException
      
                     * @throws IOException
      
                     */
      
                     public void waitForElementToClickAble(WebDriver driver,
                      WebElement element) throws IOException, ParseException {
      
                    WebDriverWait wait = new WebDriverWait(driver, jsonlib.getValueFromJSONConfig("explicitlyWait_TimeOut"));
      
                    wait.until(ExpectedConditions.elementToBeClickable(element));
      
                    }
      
                    public void waitForElementTovisibal(WebDriver driver, 
                    WebElement element) throws IOException, ParseException {
      
                    WebDriverWait wait = new WebDriverWait(driver, 
                    jsonlib.getValueFromJSONConfig("explicitlyWait_TimeOut"));
      
                    wait.until(ExpectedConditions.visibilityOf(element));
      
                    }
      
                    /**
      
                     * used to switch to Alert window & click on OK button
      
                     */
      
                     public void switchToAlertWindowAndAccept(WebDriver driver) {
      
                    driver.switchTo().alert().accept();
      
                    }
      
                    /**
      
                     * used to switch to Alert window & click on Cancel button
      
                     */
      
                     public void switchToAlertWindowAndCancel(WebDriver driver) {
      
                    driver.switchTo().alert().dismiss();
      
                    }
      
                    /**
      
                     * used to switch to Frame Window based on index
      
                     */
      
                     public void switchToFrame(WebDriver driver,int index) {
      
                    driver.switchTo().frame(index);
      
                    }
      
                    /**
      
                     * Used to Switch to Frame Window based on Id and Name Attribute
      
                     */
      
                     public void switchToFrame(WebDriver driver, 
                     String idNameAttribute) {
      
                    driver.switchTo().frame(idNameAttribute);
      
                    }
      
                    /**
      
                     * Used to select the value from the drop down based on index.
      
                     */
      
                     public void select(WebElement element, int index) {
      
                    Select sel = new Select( element);
      
                    sel.selectByIndex(index);
      
                    }
      
                    /**
      
                     * used to select the value from the drop down based on visible text
      
                     */
      
                     public void select(WebElement element, String text) {
      
                    Select sel = new Select(element);
      
                    sel.deselectByVisibleText(text);
      
                    }
               
                
      • Excel Utility: This is used for excel operations like getting some saved attributes etc
      • File Utility: This is used to read/write file
      • Listener and Retry Listener Implementation: This is used for extent report generation

2. POM / Object Repository

It is a collection of reusable web elements and a business library that be used for specific businesses or projects. In order to develop we have used POM design pattern as per the rule automation element locator should not be hard coded in the test script because maintenance and modification is tedious job whenever requirement is changed. In real-time most organizations follow the Agile process, where frequent requirement changes should be handled, in such cases, POM repository helps us to maintain and modification becomes easier.


  • 3 Test Data

    It is one of the components in the framework and contains the data which is required to run the framework. There are two types of data:

    • A. Common Data:
      1. URL: Used to run test scripts in a different environment.
      2. User Name / Password: Used to run the application with different Credentials
      3. Browser: used to run all the test scripts in different browsers.

      Example

                   
                    public class FileUtility {
      
                      package com.automation.blog.geniricutility;
      
                      import java.io.FileInputStream;
      
                      /**
      
                       * used to read the data from commonData.property file based on key which you pass
                        as an argument.
      
                       * @param key
      
                       * @return
      
                       * @throws Throwable
      
                       */
      
                       public String getPropertyKeyValue(String key) throws Throwable {
      
                      FileInputStream fis  = new FileInputStream("./TestData/commonData.property");
      
                      Properties pobj = new Properties();
      
                      pobj.load(fis);
      
                      return pobj.getProperty(key);
      
                        }
      
                      }
                
                 
    • B. Test Script Data :

      Data that is required for all the test scripts. Every test script is dedicated to a JSON file. As per the rule of automation, data should be externalized because modification maintenance is easier.


      Example

                   
                    package com.automation.blog.geniricutility;
      
                    import java.io.FileReader;
      
                    public class JsonUtility {
      
                    public String getValueFromJSON(String key) throws IOException, ParseException{
      
                    JSONParser jsonParser = new JSONParser();
      
                    JSONObject jsonObject = (JSONObject)jsonParser.parse(new FileReader("TestData/testdata.json"));
      
                    String value = (String) jsonObject.get(key);
      
                    return value;
      
                    }
      
                    }
                
                 

4. Resource

It is one of the components in the framework which contains resources to run the Framework like IE-Driver-Server, Chrome-Driver-Server, Gecko-Driver-Server, User-Guide Document.


5. Test scripts

It contains a collection of TestNG test scripts which is automated using @Test. During test script development make sure generic libraries and object repository is being used. In real-time whenever manual test cases are allocated to us, we should create a separate package for a module and develop a test script by taking utility.

Example

             
              package com.automation.blog.queue.ccqueue;

              import java.awt.AWTException;

              @Listeners (com.automation.blog.geniricutility.ListenerImplementation.class)

              publicclass CCQueue extends BaseClass {



              @Test(priority = 0)

              public  void ccQueue() throws IOException, ParseException {

              PlatformPage pf = new PlatformPage(driver);

              pf.queueLink();

              }



              @Test(priority = 1)

              public  void getPaymentDetails() throws IOException, ParseException {

              CCQueuePage ccq = new CCQueuePage(driver);

              ccq.paymentDetails();

              }



              @Test(priority = 2)

              public  void verifyAndClickOnViewHistoryButton() throws IOException, ParseException {

              CCQueuePage ccq = new CCQueuePage(driver);

              ccq.verifyAndClickOnViewHistoryButton();

              }

              @Test(priority = 3)

              public  void verifyAndClickOnUserHistoryButton() throws IOException, ParseException {

              CCQueuePage ccq = new CCQueuePage(driver);

              ccq.verifyAndClickOnUserHistoryButton();

              }



              @Test(priority = 4)

              public  void verifyAndClickOnCoupon() throws IOException, ParseException {

              CCQueuePage ccq = new CCQueuePage(driver);

              ccq.verifyAndClickOnCoupon();

              }

              @Test(priority = 5)

              public  void verifyAndClickOnDigitizationHistoryButton() throws IOException, ParseException {

              CCQueuePage ccq = new CCQueuePage(driver);

              ccq.verifyAndClickOnDigitizationHistoryButton();

              }

              }
          
           

6. Driver/XML File

It is a TestNG component used to execute all the test scripts in the batch, parallel, or group. In real-time whenever we get a new build, we should create a test NG.xml and trigger the execution.

Example

             
                <?xml version="1.0" encoding="UTF-8"?>

                <suite name="Suite" paralle="tests" thread-count="3">

                <listeners>

             <listener class-name="com.automation.blog.geniricutility.ListenerImplementation.class">

             </listener>

             </listeners>

             <test thread-count="3" parallel="tests" name="Test-runner1">

             <classes>

             <class name="com.automation.blog.communication.with.whatsapptest.P1CommunicationWithWhatsappTest"/>

             </classes>

             </test>

             <test name="Test-runner2">

             <classes>

             <class name="com.automation.blog.communication.with.emailtest.P1HTMLBasedEmailTest"/>

             </classes>

             </test>

             <test name="Test-runner3">

             <classes>

             <class name="com.automation.blog.communication.with.smstest.P1TextonlyWithSMSTest"/>

             </classes>

             </test>
             </suite>
          
           

7. HTML Report

Whenever TestNG execution is completed it automatically generates an HTML report which helps us to know the status of the application. In Real-time reporting component is very much important because it provides the quality of the application and the same report is being submitted to the customer. In real-time report helps the engineer to know the root cause of the issue whenever the test Script is getting failed.


Example

             
               package com.automation.blog.geniricutility;

               import java.io.File;

              /*

              * Class contains Listener Implementation Specific libraries which includes Screenshots on TestFailure

              * @author author name

              *

              */

              public class ListenerImplementation implements ITestListener, WebDriverEventListener{

              JavaUtility jlib1 = new JavaUtility();

              ExtentReports report;

              ExtentTest test;

              // create test name in report

              public void onTestStart(ITestResult result) {

              test = report.createTest(result.getMethod().getMethodName());

              String path = System.getProperty("user.dir");

              String otherFolder = path + "//ExtentReport";

              File directory = new File(otherFolder);

                  File[] files = directory.listFiles();

                  for (File f : files)

                  {

                      if (f.getName().startsWith("ExtentReport"))

                      {

                        f.delete();

                      }

                  }

              }

              //log for pass test method

              public void onTestSuccess(ITestResult result) {

              test.log(Status.PASS, result.getMethod().getMethodName()+"is passed");

              }

              //Log for failed Method

              public void onTestFailure(ITestResult result) {



              String testName = result.getMethod().getMethodName();

              test.log(Status.FAIL, testName + "is failed");

              test.log(Status.FAIL, result.getThrowable());

              DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("ddMMyyyy HHmmss");

              String date = dateFormatter.format(LocalDateTime.now());

              EventFiringWebDriver edriver = new EventFiringWebDriver(BaseClass.sdriver);

              File srcFile = edriver.getScreenshotAs(OutputType.FILE);


              File destFile = new File("./ScreenShot/" + testName + "-" + date + ".png");

              test.addScreenCaptureFromPath(destFile.getAbsolutePath());

              try {

              FileUtils.copyFile(srcFile, destFile);
              }

              catch (IOException e) {

              System.out.println("=====Exception Caught====");

              }


              // It is used for Retry Analyzer it will Execute Only when the Script Failed

               Reporter.setCurrentTestResult(result);

                   if(result.getMethod().getRetryAnalyzer(result).retry(result)) {

                   result.setStatus(ITestResult.SKIP);

                   Reporter.setCurrentTestResult(null);

                   }

              }


              //log for skipped test method

              public void onTestSkipped(ITestResult result) {

              test.log(Status.SKIP, result.getMethod().getMethodName()+ "is Skipped");

              test.log(Status.SKIP,result.getThrowable());

              }

              public void onTestFailedButWithinSuccessPercentage(ITestResult result) {

              }
              public void onTestFailedWithTimeout(ITestResult result) {
              }

              public void onStart(ITestContext context) {

              DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("ddMMyyyy HHmmss");

              String date = dateFormatter.format(LocalDateTime.now());

              String fileName = "ExtentReport" + date;

              //ExtentSparkReporter spark = new ExtentSparkReporter("./ExtentReport/" + folderName + "/" +fileName+".html");

              ExtentSparkReporter spark = new ExtentSparkReporter("./ExtentReport/"+fileName+".html");

              spark.config().setDocumentTitle("Blog Admin");

              spark.config().setTheme(Theme.DARK);

              spark.config().setReportName("Automation Excecution Report");

              //Attaching the configuration to extent report and also System Info

              report = new ExtentReports();

              report.attachReporter(spark);

              FileUtility flib = new FileUtility();

              report.setSystemInfo("OS",System.getProperty("os.name"));

              report.setSystemInfo("Platform","Windos");

              report.setSystemInfo("Reporter Name", "Hritik");

              try {

              report.setSystemInfo("url",flib.getPropertyKeyValue("url"));

              }catch(Throwable e) {

              e.printStackTrace();

              }

              }

              public void onFinish(ITestContext context) {

              report.flush();

              }

              }
          
           

8. Screen Shots

Whenever any test script fails during execution, a screenshot is saved in the screenshot folder. This screenshot can be used for debugging script failure causes and raising defects in JIRA/any tool.


Example

             
              /**

              * Used to capture the screen shots

              * @param driver

              * @param tname

              * @throws IOException

              */
              public void takeScreenshot(WebDriver driver, String screenshotName) throws Throwable {

              TakesScreenshot ts = (TakesScreenshot)driver;

              File src = ts.getScreenshotAs(OutputType.FILE);

              File dest = new File("./ScreenShot/Communication"+screenshotName+".PNG");

              Files.copy(src, dest);

              }
          
           

9. Maven

When multiple engineers work with the same framework, there might be chances one engineer's changes might affect the entire framework, to avoid this kind of issue we use Maven.

Advantages of Maven

  • Check the integration & compilation issue between the framework component whenever modification, addition deletion happened in the same framework
  • Use to handle dependencies jars
  • Create framework configuration as all the required dependencies and versions are declared in POM.xml. 
  • Provides framework folder structure
  • Used to run the test script from the command line without using Eclipse/IDE
  • Used to check whether framework build is broken or not
  • Used for CD/CI[Jenkins]

Create New Maven Project

Maven Project
Create Maven

Example

             
              <dependency>
              <groupId>org.seleniumhq.selenium</groupId>
              <artifactId>selenium-java</artifactId>
              <version>3.141.59</version>
         
              </dependency>
                
                <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.0.0</version>
                </dependency>
                <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.0.0</version>
                </dependency>
          
           

10. Jenkins

Jenkins is an open source automation server. It helps automate the parts of software development related to building, testing, and deploying. It is used to execute selenium test scripts in any testing environment.

Advantages of Jenkins

  • Jenkins Provide 3 level of execution
    • On-demand: based on Customer demand we can start the execution
    • On-Scheduling: based on the scheduled time, start the execution automatically
    • POLL SCM: where continuously monitor the SCM(GitHub) & automatically start the execution whenever we get a new Build / one new test script is getting added to Git
  • Jenkins sends out an execution Report via email, once execution is completed

Conclusion

Selenium is a browser automation framework. It provides several tools and APIs for automating user interaction on pure HTML and JavaScript applications in browsers such as Internet Explorer, Mozilla Firefox, Google Chrome, Safari, etc.


Read more blogs here