Friday, 27 January 2017

How to create Hybrid Framework with Maven, TestNG, and selenium



There is a lot of confusion about hybrid frame work and how to implement it.Now there are multiple ways you can create Hybrid framework , one simple thing to remember while creating a hybrid framework is that it has the features of both data driven and keyword driven features.


Data Driven and Key word driven frameworks will not be discussed in this post, you have to have prior knowledge of the both in order to understand this particular post. Readers of this post must have working knowledge on Maven, TestNG and Selenium.



To get started I will give you a small idea of how our test subject look like.


Click to enlarge

Lets assume that it has three pages Configure source , Group data , and Drill down.
Automating the subject includes clicking, selecting or interacting with the elements present on each page.

Click to enlarge
Above you can get a brief idea of the structure and interaction of the Framework.
The three pages has three java classes assigned to it .
1.  Configuresource.java
2.  Groupdata.java
3.  Drilldown.java

We have created two TestNG test classes, which contains the different test scenarios for the three pages. The test classes.
1.Test1.java
2. Test2.java

we also have a Testdata.xlsx which looks something like this and contains the Object name, Object type,and data to be send or written in case we have any.The word Object here refers to elements present in a page.
Click to enlarge
We have a utility class named ExcelUtil.java as you can see in the flow chart Which picks the particular values from the excel and passes to the test classes.Which then passed as parameter to the page class( e.g configuresource.java) functions(referred in next paragraph) parameter. To give you a more clearer picture following is the screen shot of a test class.
Click to enlarge


each of the pages contain few actions.Each action is represented by a function which interacts with an element present in the page.Lets say, the configure source has an element A , and it needs to be clicked , then we have a corresponding function called AClicker() which will click the element A.Here is the screen shot of configure source page.


Click to enlarge
 In the above picture , you can notice that the ConfigureSource class has a method called SelectDataProvider , the parameters to the functions are the Propertyname for the Element to be selected and the type of the property(Xpath,Id etc).

The test classes pass the respective propertyname and the propertyType from the excel like the following. (Refer to the test class screenshot above also)


The page class then calls the ElementsSelectorUtil class method  to get the elements and passes the ObjectName, and Object Type as parameter.
Click to enlarge


Here is how the code for ElementSelectorUtil looks like





package UtilityClasses;

import java.util.List;
import java.util.Properties;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class ElementSelectorUtil {
     WebDriver driver;
        public ElementSelectorUtil(WebDriver driver){
            this.driver = driver;
        }
//        public WebElement perform(Properties p,String operation,String objectName,String objectType,String value) throws Exception
//        {
//          
//            return driver.findElement(this.getObject(p,objectName,objectType));
//           
//        }  
        public WebElement FindElement(By by1)
        {
            WebElement E1=driver.findElement(by1);
            return E1;
        }
        public List<WebElement> FindElements(By by1)
        {
            return driver.findElements(by1);
        }
       
        /**
         * Find element BY using object type and value
         * @param p
         * @param objectName
         * @param objectType
         * @return
         * @throws Exception
         */
        public By getObject(String PropertyValue,String objectType) throws Exception{
            //Find by xpath
            if(objectType.equalsIgnoreCase("XPATH")){
               
                return By.xpath(PropertyValue);
            }
            //find by class
            else if(objectType.equalsIgnoreCase("CLASSNAME")){
               
                return By.className(PropertyValue);
               
            }
            else if(objectType.equalsIgnoreCase("ID")){
               
                return By.id(PropertyValue);
               
            }
            //find by name
            else if(objectType.equalsIgnoreCase("NAME")){
               
                return By.name(PropertyValue);
               
            }
            //Find by css
            else if(objectType.equalsIgnoreCase("CSS")){
               
                return By.cssSelector(PropertyValue);
               
            }
            //find by link
            else if(objectType.equalsIgnoreCase("LINK")){
               
                return By.linkText(PropertyValue);
               
            }
            //find by partial link
            else if(objectType.equalsIgnoreCase("PARTIALLINK")){
               
                return By.partialLinkText(PropertyValue);
               
            }else
            {
                throw new Exception("Wrong object type");
            }
        }

}



The elementSelectorUtil returns the webElement and then you can click or send data to the element.
Below is the Entrire project structure of my project in Eclipse


Click to enlarge

Below is the code for the Utility files

ExcelUtil.java----------
**************************************************************************************************************************************************************************************************************
package UtilityClasses;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
public class ExcelUtil {

        private XSSFSheet ExcelWSheet;
        private XSSFWorkbook ExcelWBook;
        FileInputStream ExcelFile;
        StringBuilder ExcelPath=null;

        // Constructor to connect to the Excel with sheetname and Path
        public ExcelUtil(String Path, String SheetName){

            try {
                ExcelPath=new StringBuilder(Path);
                // Open the Excel file
               
                ExcelFile = new FileInputStream(new File(Path));

                // Access the required test data sheet
                ExcelWBook = new XSSFWorkbook(ExcelFile);
                ExcelWSheet = ExcelWBook.getSheet(SheetName);

                // ExcelWSheet.getRow(1).createCell(5).setCellValue("Pass");
                // ExcelWSheet.getRow(2).createCell(5).setCellValue("Fail");

            } catch (Exception e) {
                e.printStackTrace();

            }
        }

        // This method is to set the rowcount of the excel.
        public int excel_get_rows() throws Exception {

            try {
                return ExcelWSheet.getPhysicalNumberOfRows();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            return 0;
        }

        public int excel_get_columns() throws Exception {
            try {
                return ExcelWSheet.getDefaultColumnWidth();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            return 0;

        }

        // This method to get the data and get the value as strings.
        public String getCellDataasstring(int RowNum, int ColNum) throws Exception {

            try {
                String CellData = ExcelWSheet.getRow(RowNum).getCell(ColNum).getStringCellValue();

                return CellData;

            } catch (Exception e) {

                System.out.println("return 'Errors in Getting Cell Data'");
            }
            return null;
        }

        ///// This method to get the data and get the value as number.
        public double getCellDataasnumber(int RowNum, int ColNum) throws Exception {

            try {
                double CellData = ExcelWSheet.getRow(RowNum).getCell(ColNum).getNumericCellValue();

                System.out.println("The value of CellData " + CellData);
                return CellData;
            } catch (Exception e) {
                return 000.00;
            }
        }
        public void ExcelWriter(int RowNum,int ColumnNo,String Data)
        {    try {
            ExcelWSheet.getRow(RowNum).createCell(ColumnNo).setCellValue(ExcelWBook.getCreationHelper().createRichTextString(Data));
            FileOutputStream outFile = new FileOutputStream(ExcelPath.toString());
       
            ExcelWBook.write(outFile);
            outFile.close();
           
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
           
        }
  
}

***************************************************************************************************************************************************************************************************************
PropertyHanlder.java----


package UtilityClasses;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.omg.CORBA.portable.InputStream;

public class PropertyHandler {
    Properties Selector=new Properties();
   
    public String getPropertyValue(String ObjectName) throws IOException{
      
        FileInputStream input=new FileInputStream("C:\\Users\\sayan.sikdar\\workspace\\Collabion2010\\Utilities\\UtilityProperties\\Object.properties");
        Selector.load(input);
        if(input!=null)
        {
            Selector.load(input);
        }
        else
        {
            new FileNotFoundException("Error is fetching properties file"+input);
        }
        return Selector.getProperty(ObjectName);
        }

}

Here is the picture of the property object repository.

Properties File




Picture courtesy: Collabion

Note:I work as a Software Test Engineer for Collabion


Tuesday, 17 January 2017

How to generate Xpath for SVG Elements

I have seen a lot of people asking about how they can generate Xpath or some sort of locators for locating SVG elements.
well, its very simple but first lets have a look at how SVG elements look like, Have you come across this elements ever. Check out the picture  below.



Click to enlarge



If you have come across these elements but you don't know how to locate them or for people who have not yet come across these elements,how would you locate the highlighted text element using Xpath. Generate a Xpath in your mind.Is it something similar to -

.//div[@id='chartPanelContainer']//span//svg/g[contains(@class,'red-axisbottom')]/g[contains(@class,'red-x-axis-labels')]/text[1]

well this is how you select normal elements right?But this does not work for SVG elements.

for SVG elements you have to use the format /*[name()='svg'] instead of /svg. Look at the below picture to understand how it works-


Click to enlarge

Wednesday, 4 January 2017

Few things about handling those nasty dynamic elements using Xpath

Have you ever come across a situation where you struggle to find a stable Xpath of a element .I know it's frustrating, It is even more frustrating when elements of your test subject tend to change their paths with each version.Here are some tweaks applied by automation engineers to handle dynamic element and find stable Xpaths.


Scenario1: Dynamic elements with text as innerHTML.

In the below image you can see that the highlighted div has dynamic parents so it is impossible to find a relative Xpath based on the parent element.There are numerous div elements with the same class name on top of that that class name has a space which makes it fairly impossible to find a stable Xpath.
Dynamic Element Xpath in Selenium

How ever you can use the following text() function to match the innerHTML of the div.

Dynamic Element Xpath in Selenium


Scernario 2: Dynamic SVG element.


 In the following picture you can see a SVG element which has a dynamic class name.How to handle that.
Dynamic Element Xpath in Selenium

 In my scenario , the position of <g> element is at 9th.However this might change with each release of the product I am testing.How to handle this kind of situation.For this you can use the contains function like following.


Dynamic Element Xpath in Selenium







Scenario 3:Multiple elements with same xpath

In the following picture the inputs has similar relative Xpath.
Dynamic Element Xpath in Selenium


You can use the (..) operator for handling this kind of situation. As the label text is constant for each elements.
Dynamic Element Xpath in Selenium




Thanks I hope this helps you.


























Thursday, 29 December 2016

GeckoDriver -The new girl in town

The new buzz word in QA town is GeckoDriver. You have come across these words quite a few times in last few days.So what is this GeckoDriver?

 Firefox driver which was the default web driver for firefox is no longer supported with Firefox 47 and further. To drive Firefox from now on you have to use Marionette GeckoDriver.


How to use Marionette GeckoDriver?

  •   Download GeckoDriver from Github
  •   Unzip the zipped file and extract the executable file for GeckoDriver.
  •   Rename the executable file to wires.exe (Official recommendation )
  •   Set the path of "webdriver.gecko.driver" using setProperties method.
  •   Initiate your MarionetteDriver.
Below is the code snippet you can use to work with Marionette Driver.

    System.setProperty("webdriver.gecko.driver", "D://work folder//wires.exe");
    WebDriver driver = new MarionetteDriver(); 


How to open Firefox with a custom profile with help of Marionette Driver?

Marionette driver  does not support passing a profile object as a argument to driver constructor like FirefoxDriver(ProfileObject). In order to do that you have to first instantiate a capability object and then add the profile object to the capability.
Once you have done that you can now instantiate your MarionetteDriver with the capability object as constructor argument.





 More updates on GeckoDriver is coming as I get more time to check her out! Adios!