Saturday, September 16, 2017

Excel Read Write Library over Apache POI

Maven Dependency

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>


 Simple Library class for Excel Read and Write operations using Apache POI
package com.apache.excel.example;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelOperations {

 Workbook workbook;
 
 public ExcelOperations(String filePath) {
  try {
   workbook = new XSSFWorkbook(filePath);
  } catch (IOException e) {
   throw new RuntimeException("Error while reading workbook",e);
  }
 }
 public ExcelOperations() {
  workbook = new XSSFWorkbook(); 
 }
 public Object getValue(int sheetIndex, int rowIndex,int colIndex){
  Sheet sheet = workbook.getSheetAt(sheetIndex);
  return getValue(sheet, rowIndex, colIndex);
 }
 public Object getValue(String sheetName, int rowIndex,int colIndex){
  Sheet sheet = workbook.getSheet(sheetName);
  return getValue(sheet, rowIndex, colIndex);
 }
 public Object getValue( int rowIndex,int colIndex){
  
  return getValue(workbook.getActiveSheetIndex(), rowIndex, colIndex);
 }
 public Object getValue(Sheet sheet, int rowIndex,int colIndex){
  Object value =null;
  Cell c = sheet.getRow(rowIndex).getCell(colIndex);
  switch (c.getCellType()) {
  case STRING:
   value= c.getStringCellValue();
   break;
  case NUMERIC:
   value=c.getNumericCellValue();
   break;
  case _NONE:
  case BLANK:
   value="";
   break;
  case ERROR:
   value="#ERR#";
   break;
  case BOOLEAN:
   value = c.getBooleanCellValue();
   break;
  case FORMULA:
   value= c.getCellFormula();
   break;
  default:
   break;
  }
  return value;
 }
 public int getRowCount(){
  return activeSheet().getLastRowNum()+1;
 }
 private Sheet activeSheet(){
  int index = workbook.getActiveSheetIndex();
  return workbook.getSheetAt(index);
 }
 public int getColumnCount(int rowIndex){
  return getRow(rowIndex).getLastCellNum();
 }
 private Row getRow(int rowIndex) {
  return activeSheet().getRow(rowIndex);
 }
 public void save(String saveToFilePath) {
  try {
   FileOutputStream fos = new FileOutputStream(saveToFilePath);
   workbook.write(fos);
   fos.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 public void setValue(int rowNo, int cellNo,  Object value) {
  setValue(workbook.getActiveSheetIndex(), rowNo, cellNo, value);
 }

 public void setValue(int sheetIndex, int rowNo, int cellNo,  Object value) {
  
  Sheet sheet = workbook.getSheetAt(sheetIndex);
  setValue(sheet, rowNo, cellNo, value);
 }
 public void setValue(String sheetName, int rowNo, int cellNo, Object value) {
  Sheet sheet = workbook.getSheet(sheetName);
  setValue(sheet, rowNo, cellNo, value);
 }
 public void setValue(Sheet sheet, int rowNo, int cellNo,  Object value) {
  
  Row row = sheet.getRow(rowNo);
  if(row==null){
   row = sheet.createRow(rowNo);
  }
  Cell cell = row.getCell(cellNo);
  if(cell==null){
   cell = row.createCell(cellNo);
  }
  writeToCell(cell,value);
  
 }
  void closeReading() {
  try {
   workbook.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }
 public void createSheet(String sheetName) {
  Sheet sheet = workbook.getSheet(sheetName);
  if(sheet==null){
   workbook.createSheet(sheetName);
   int index = workbook.getSheetIndex(sheetName);
   workbook.setActiveSheet(index);
  }
 }
 public void write2DData(Object[][] data, int startRowIndex, int startColIndex) {
  
  Sheet sheet = activeSheet();
  for (int i = 0; i < data.length; i++) { // iterate over rows (i is row offset counter)
   Row row = sheet.getRow(startRowIndex+i);
   if(row==null){
    row = sheet.createRow(startRowIndex+i);
   }
   writeToRow(row,data[i],startColIndex);
  }
 }
 private void writeToRow(Row row, Object[] data, int startCellNo) {
  for (int j = 0; j < data.length; j++) { // iterate over columns, j is column offset index
   Cell cell = row.getCell(startCellNo+j);
   if(cell == null){
    cell = row.createCell(startCellNo+j);
   }
   writeToCell(cell,data[j]);
  }
 }
 private void writeToCell(Cell cell, Object valueObject) { 
  if(valueObject instanceof String) {
   cell.setCellValue((String)valueObject);
  }
  else if(valueObject instanceof Integer || valueObject instanceof Double || valueObject instanceof Float || valueObject instanceof Long){
   
   Double doubleValue = Double.parseDouble(valueObject.toString());
   cell.setCellValue(doubleValue);
  }else if(valueObject instanceof Boolean){
   cell.setCellValue((Boolean) valueObject);
  }else if(valueObject instanceof Date){
   cell.setCellValue((Date)valueObject);
  }else if(valueObject instanceof Calendar){
   cell.setCellValue((Calendar)valueObject);
  } 
 }
}

Mobile Device - Perform Swipe / Scroll

Example : How to perform Swipe screen using Appium for Mobile device.


package com.vikas.automation.example;

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.Test;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;

public class AndroidLinkedInTest {

 @Test
 public void testMobileSwipe() throws MalformedURLException {

  URL appiumUrl = new URL("http://127.0.0.1:4723/wd/hub");
  DesiredCapabilities caps = new DesiredCapabilities();
  caps.setCapability(MobileCapabilityType.APP,
    "C:\\Users\\vikas\\O2\\apps\\BookMyShow_5.3.0.apk");
  caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "android");
  caps.setCapability(MobileCapabilityType.DEVICE_NAME, "OnePlus3T");
  caps.setCapability(MobileCapabilityType.NO_RESET, true);
  caps.setCapability(MobileCapabilityType.FULL_RESET, false);
  //caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "");
  caps.setCapability(AndroidMobileCapabilityType.APP_WAIT_ACTIVITY, "*");
  AppiumDriver<WebElement> driver = new AndroidDriver<WebElement>(appiumUrl, caps);
  driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

  //swipeUp(driver);
  swipeToRight(driver);
  System.out.println("Swipe completed");
  
  driver.quit();
 }

 private void swipeUp(AppiumDriver<WebElement> driver) {

  System.out.println(driver.manage().window().getSize());
  TouchAction action = new TouchAction(driver);
  // Just for beginning and manking it simple lets hardcode the x and y 
  int startX = 540;
  int startY = 1680;
  int endX = 540;
  int endY = 240;
  // Only need to give start and end point, No need of offset
  action.press(startX, startY).waitAction(Duration.ofMillis(500)).moveTo(endX,endY).release().perform();
  
 }
 private void swipeToRight(AppiumDriver<WebElement> driver) {

  // Take dynamic X and Y coordinates , below code should support devices with diffrent screen sizes
  Dimension d =driver.manage().window().getSize();
  int y = d.height/2;
  int endX = d.width/4;
  int startX = endX * 3;
  TouchAction action = new TouchAction(driver);  
  action.press(startX, y).waitAction(Duration.ofMillis(500)).moveTo(endX,y).release().perform();
 }
}

Friday, August 18, 2017

Customizing ExtentReport : Adding External Link

Extent Report  (http://extentreports.com/) is undoubtedly a great Reporting Library for any test automation framework.

Below is one example of how to customize ExtentReport for your project need.

The example will guide you on How to add a Hyperlink into HTML report.



Step 1: Create your own class as below

import com.aventstack.extentreports.markuputils.Markup;

/**
 * Class that represents Hyperlink
 */
class ExtentLink implements Markup {
private String linkUrl;
public String getLinkUrl() {
return this.linkUrl;
}
public void setLinkUrl(String linkUrl) {
this.linkUrl = linkUrl;
}
public String getLinkText() {
return this.linkText;
}
public void setLinkText(String linkText) {
this.linkText = linkText;
}
private String linkText;
@Override
public String getMarkup() {
                final String htmlTag = "+this.linkText+";
                return htmlTag;
}
@Override
public String toString() {
return this.linkText;
}

}

*Target is specified as _blank so the link will open in new window. You you wants to open in same window then remove target='_blank'

Step 2: Create object of ExtentLink and add it to Extent Log as below

ExtentReports extent = new ExtentReports();
ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter("extent.html");
extent.attachReporter(htmlReporter);
//start of test case
ExtentTest test = extent.createTest("TestName");
//....
//Add a link in test report
final ExtentLink link = new ExtentLink();
link.setLinkText("Link Text goes here");
link.setLinkUrl("http://somedomain.com");
test.log(Status.INFO, link);
//...
//..
// Now Save report
extent.flush();


Thats All you need!!

Conclusion:
You can easily customize ExtentReport by adding any  HTML object like Links, Label, Tables, Image with the help of "Markup" class.

Sunday, May 14, 2017

Tutorial : Setting up Selenium GRID in LAN

Trying to learn and set up selenium GRID in local network? Here is the simple tutorial to start with.

Selenium GRID - components

  1. Selenium GRID Hub
  2. Selenium GRID Node

Step 1: Start Selenium GRID HUB Server 

java  -jar selenium-server-standalone-3.3.1.jar -role hub

After running this command you will a message as  below

16:55:49.766 INFO - Selenium Grid hub is up and running
17:16:34.636 INFO - Nodes should register to http://192.168.0.128:4444/grid/register/

Step 2: Start Selenium GRID NODE

2.1 Go to node machine & node configuration file with below JSON

FileName: nodeConfiguration.json


   "capabilities":[ 
      { 
         "browserName":"chrome",
         "maxInstances":10,
         "platform":"WIN8",
         "version":"58",
         "seleniumProtocol":"WebDriver"
      },
      {
         "browserName":"firefox",
         "maxInstances":3,
         "platform":"WIN8",
         "version":"53",
         "seleniumProtocol":"WebDriver"
      }
   ],
   "debug":false,
   "proxy":"org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
   "register":true,
   "registerCycle":5000,
   "maxSession":6
}

 2.2 Execute below command to start node and connect to hub

java -Dwebdriver.chrome.driver=C:\Users\vikas\selenium_drivers\chromedriver.exe -Dwebdriver.gecko.driver=c:\geckodriver.exe -jar selenium-server-standalone-3.3.1.jar -role node -nodeConfig nodeConfigFile.json -hub http://192.168.0.128:4444/grid/register

Step 3: Confirm Node is connected and hub is running by opening below url in browser

http://192.168.0.128:4444/grid/console

Step 4: Run Test case from eclipse. below is the sample code.

package com.vikas.samples;

import java.net.MalformedURLException;
import java.net.URL;

import org.apache.tools.ant.taskdefs.XSLTProcess.TraceConfiguration;
import org.openqa.selenium.By;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import com.vikas.framework.core.Browser;

public class GridExecutionDemo {

    @Test(dataProvider = "multipleTests")
    public void testOnRemmoteChromeBrowser(int testNumber, String browserName) throws MalformedURLException {
      
        // WebDriver driver = new ChromeDriver();
        System.out.println("Starting test :" + testNumber);
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setBrowserName(browserName);
        caps.setPlatform(Platform.WIN8);
        // OR caps.setCapability("browserName", "chrome");
        URL hubUrl = new URL("http://192.168.0.128:4444/wd/hub");

        WebDriver driver = new RemoteWebDriver(hubUrl, caps);
        driver.get("http://google.com");
        driver.findElement(By.name("q")).sendKeys("Vikas Thange Selenium");

        driver.quit();
    }

    @DataProvider(parallel = true)
    public Object[][] multipleTests() {
        return new Object[][] { { 1, "firefox"}, { 2, "chrome" } };
    }
}

Tuesday, October 25, 2016

Opening url in new Window?


How to open a new window with a new URL while browser automation session is ongoing?


Have you encountered situation where you are automating a website and same time you need to open other browser window to do something like read OTP or read E-Mail and come back to the AUT window and proceed automation...

I am sure If you are working in web automation testing you might have encountered this.

What solution we have ?
  1. Launch a new WebDriver instance while one is having AUT loaded.
    • For example below code :
      // Initial WebDriver instance to perform Automation Testing on AUT
      // (if Selenium 3.0 then set webdriver.gecko.driver path)
      WebDriver driver = new FirefoxDriver();
      driver.get("http://myAUT.com");
      // TODO: perform some automation stuff
      // ....
      // Now I want to open gmail in new window without disturbing
      // myAUT.com site
      // So launch a new WebDriver instance 
      WebDriver gmailBrowser = new FirefoxDriver();
      gmailBrowser.get("http://www.gmail.com");
      // Perform operations like read mail data here
      // String otp = gmailDriver.findElement(By.xpath("some locator"))
      // .getText(); 
      // Now close browser and go back to myAUT.com
      gmailBrowser.close();
      // now type otp in myAUT.com
      driver.findElement(By.id("some id")).sendKeys(otp);
      

    • But is this really good approach? NO!!! absolutely not! 
    • Because it's more confusing to work on two webdriver instance at a time.
    • Both WebDriver instance do not share common session with server.
  2. Launch a new url in new tab of existing WebDriver session
    • Why to start a new WebDriver instance when you do use already existing one?
    • This will also share existing session with server
    • Approach: - 
      • Execute a JavaScript code it will open a new url in new tab/window but in existing WebDriver instance
      • Switch driver to point newly opened driver and do some task
      • Once you are done close newly opened tab/window and switch back to AUT browser window
    • Below is the sample script
      WebDriver driver = new FirefoxDriver();
      WebDriver driver = new FirefoxDriver();
      driver.get("http://google.com");
      // copy current window handle for future reference
      String autWindowHandle = driver.getWindowHandle();
      JavascriptExecutor executor = (JavascriptExecutor) driver;
      executor.executeScript("window.open('http://www.gmail.com','_blank')");
      
      // Switch driver to gmail and do your work
      for (String handle : driver.getWindowHandles()) {
       driver.switchTo().window(handle);
      }
      // do operations and read data.
      // String otp = driver.findElement(By.id("some id")).getText();
      
      //Now close gmail and switch back to AUT site
      driver.close();
      driver.switchTo().window(autWindowHandle);
      //Continue automation testing
      
I hope this will be useful to solve your problem.

Saturday, October 22, 2016

Handling unexpected poupus and alerts while automation with selenium webdriver



Hi All,
Today I just thought it’s been a long time I wrote my last blog and I should post another one. Meantime on what’s app group one of my friend asked question on how to deal with the unexpected popup message while automation was going on. I am sure most of the automation testers are still facing the same issue and trying to figure out a solution to this problem. 

QTP gives a very nice feature to handle such a conditions with the help of “recovery scenario manager” features which works on different triggers like popup dialogue. But when it comes to WebDriver automation on one hand we get freedom to choose whichever framework / methodology but on other we don’t get any built in features like “Recovery Manager Scenario” instead we have to code it.

So here I am going to post a solution with the code example on handling unexpected poupus / dialog boxes or alert messages encountered during webdriver automation.
  
The first thing first “Unexpected popups / dialogue boxes or alert messages are not really UNEXPECTED”. The popup messages like survey or feedback are expected to get displayed in application but one cannot predict when it will be displayed in application. It doesn’t make sense to have a if….else.. condition after every webdriver action.

I propose 2 solutions to this problem

Approach 1: Using a very simple approach
This solution is only applicable for framework which is not built on Page object model. If your framework is having Page Object model pattern please go with approach #2.

Do not allow the driver to freely flowing all over the project, Use encapsulation and abstraction to keep driver in one class and write dependent methods in same class. As this framework approach do not allow driver to get freely accessible anywhere in the project except this class.

Simple example is as ->





Use the Object of this WebDrivreFace class to perform all operations on driver. Don’t allow driver access outside of this class and always use getElement() & isDisplayed () methods before doing any direct operations on element.

Sample code to use this type of framework example –

WebDriverFace face = new WebDriverFace(); // initialize driver in constructor
face.openUrl(“http://samplewebsite.com”);
face.click( By.linkText(“sign in”) );
face.type( By.id(“userid”), “username@domain.com”);
face.type( By.id(“password”), “myAW3somep@55word”);

If there is any popup / dialog displayed matching with our text or locator the it will closed. J

Approach 2: using Page Object model
                If your framework is using Page Object model to initialize page Objects then use below technique.

                Have a common generic method to initialize all page class objects from your class. Make sure after every time you create a object you call a method which will check and handle popups.

High level code will look like this ->

Class Page is base class for all other pages class with below method ->

 class Page{
                public void handlePopupsAndAlerts(){
                                // use loop and check if any popup locator is displayed
                                // if displayed then write a code close it here.
                }
public static T getPageObject(WebDriver drver, Class clazz) {
                               
                                T pageObject = (T)PageFactory.initElements(driver, clazz);
                                pageObject. handlePopupsAndAlerts();
                                return pageObject;
                }
}
 
How to use this code to create page object?

LoginPage loginPage = Page. getPageObject(driver,LoginPage.class);
loginPage.performLogin();
 
So in above example as soon as the new page is loaded in browser we should create object as mentioned above. While initializing every page object it will execute handlePopupsAndAlerts() method to find and handle all types of popups and alerts.