Friday, April 15, 2011

Why Load Testing from the Cloud Doesn't Work

Thursday, April 7, 2011

Selenium - Capture Screenshot using TestNG

Selenium - Capture Screenshot using TestNG

It is always a best practice to capture a screen shot on error, so that we can easily analyze the issue.
With prior experience on Hybrid Framework using QTP, I have considered following points while creating the Screen capture logic.

1. Reduce the screen capture code redundancy.
As we write test in different methods, in-order to capture the screen shot on error, we need to wrap every test method in the following way
try { 
// test here
    } catch (Throwable e) { 
      // capture screenshot here
    }
How to over come this redundancy?
TestNG provide Listeners and Reporters through which we can generate custom reports.
In this example I am extending TestListenerAdapter, which implements ITestListener with empty methods, so that I don't have to override other methods of the interface that I am not interested.
I have decided to use onTestFailure method to capture the screen shot as it is invoked once test fails.

2. File naming convention
It is better to name the file using time stamp, so that we can easily understand when this error occurred.
Apart from this I also append the file name with IP address that can help me in identifying on which system this error occurred, assuming you are working on different browser combinations from different locations.

26_Mar_2011__02_51_33PM_171.22.0.111.png

3. Where to store the file
Store all the files in separate folder inside the working directory. I use separate folder called "ScreenShots".

C:\eclipse\MyWorkSpace\Implements23\ScreenShots\26_Mar_2011__02_51_33PM_132.22.0.111.png

4. How to view the files
I am directly inserting the file names in the test reporter, so that screen shot appear as hyper link.


5. Image file format
I prefer using PNG format.

Following is the code written using above mentioned points.

Note: I am not using "selenium.capturescreeshot" method, using custom logic to capture screenshot which I feel is easy. This will work even without selenium. I am using Selenium interface, didn't find way to refer the selenium object in the TestNG listeners.

package package1;

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.*;
import org.testng.TestListenerAdapter;
import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.lang.*;
import java.net.*;

public class TestNGCustom extends TestListenerAdapter {
private int Count = 0;

//Take screen shot only for failed test case
@Override
public void onTestFailure(ITestResult tr) {
ScreenShot();
}

@Override
public void onTestSkipped(ITestResult tr) {
//ScreenShot();
}

@Override
public void onTestSuccess(ITestResult tr) {
//ScreenShot();
}

private void ScreenShot() {
try {

String NewFileNamePath;

/*
//Code to get screen resolution
//Get the default toolkit
Toolkit toolkit = Toolkit.getDefaultToolkit();
//Get the current screen size
Dimension scrnsize = toolkit.getScreenSize();
//Print the screen size
System.out.println ("Screen size : " + scrnsize);
*/    

//Get the dir path
File directory = new File (".");
//System.out.println(directory.getCanonicalPath()); 

//get current date time with Date() to create unique file name
DateFormat dateFormat = new SimpleDateFormat("dd_MMM_yyyy__hh_mm_ssaa");
//get current date time with Date()
Date date = new Date();
//System.out.println(dateFormat.format(date));

//To identify the system
InetAddress ownIP=InetAddress.getLocalHost();
//System.out.println("IP of my system is := "+ownIP.getHostAddress()); 

NewFileNamePath = directory.getCanonicalPath()+ "\\ScreenShots\\"+ dateFormat.format(date)+"_"+ownIP.getHostAddress()+ ".png";
System.out.println(NewFileNamePath);

//Capture the screen shot of the area of the screen defined by the rectangle
Robot robot = new Robot();
BufferedImage bi=robot.createScreenCapture(new Rectangle(1280,1024));
ImageIO.write(bi, "png", new File(NewFileNamePath));
Count++;//Assign each screen shot a number
NewFileNamePath = "ScreenShot"+ Count + "";
//Place the reference in TestNG web report 
Reporter.log(NewFileNamePath);


} 
catch (AWTException e) {
e.printStackTrace();
} 
catch (IOException e) {
e.printStackTrace();
}
}
}


Important Notice: When you implement TestNG interfaces, you need to inform about the listeners very early in the process, otherwise it will ignore your implemented interfaces. Following are the ways

Using -listener on the command line.
Using with ant.
Using in your testng.xml file.
Using the @Listeners annotation on any of your test classes.

I prefer using at test calass, attaching the screen shot for more clarity.

For more information refer TestNG documentation.

How to handle black/empty screen shots

Enjoy taking screen shots in Java...

Download the entire working code that is implemented in a project from the below link.

SeleniumWebdriver - Page objects Implementation - Part 2

---