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
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.
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
---
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
Using
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
---
hi, many thanks for such a wonderful utility.
ReplyDeleteI have an issue with the script that I am running currently.
My test-script runs 24x7 on a VPS. On failure, it takes a screenshot of the page, but only a black output appears in the screenshot.
can you please let me know why is this happening.
Younus,
ReplyDeleteI think this happens when the screen is locked, make sure your terminal is not closed.
salut B.M
ReplyDeleteje voudrais savoir quel sont les meilleurs outils de test de montée en charge dans le monde.
moi j'utilise neoload mais il coûte cher. merci
Hello Tlili M,
ReplyDeleteI have to use Google translate to read your text written in french.
I feel NeoLoad is cheap when compared with HP loadrunner. There are many tools available in the market, it is based on your application complexity (Ajax, flex, silver light, third party components). If your application is constructed with simple technology you can use open source tools like Jmeter. Based on my experience open source tools are not capable of handling complex applications.
Awesome post! I tried this and it works fine, however i have a question. Is there a way to tweak this so that the Report.log is on the @Test method level in the report? A perfect example would be if you have a Report.log inside @Test method, this will show the link or log inside the method level not on the reporter output section.
ReplyDeleteI tried that, but not successful.
ReplyDeleteThanks Bharath.
ReplyDeleteI have a prob,When I run the script in index.html file it added name of the screenshot as "Screenshot1" but not as a hyperlink.
can you pls help me on this.
Hello Rama,
ReplyDeleteScreen shot is stored in the following location
NewFileNamePath = directory.getCanonicalPath()+ "\\ScreenShots\\"+ dateFormat.format(date)+"_"+ownIP.getHostAddress()+ ".png";
System.out.println(NewFileNamePath);
Hyper link is created using following code
NewFileNamePath = "ScreenShot"+ Count + "";
Reporter.log(NewFileNamePath);
Do you have "ScreenShots" folder in your root directory?
Folder created in in root directory.
ReplyDeleteBut the problem is with this -
NewFileNamePath = "ScreenShot"+ Count + "";
Here I'm getting syntax error,insert';' to complete statement.
Bharath,
ReplyDeleteIts working now.I was just confused.
This is really helpful.
bharath, can we produce graphs with testng?
Hello Bharath/Rama, same error I am facing on Eclipse..syntax error,insert';' to complete statement.Can you tell me how you resolve it?
DeleteIn my case if I am using below code then report log shows ScreenShot but not hyperlink
NewFileNamePath = "ScreenShot"+ Count + "";
Reporter.log(NewFileNamePath);
And if I use NewFileNamePath = "ScreenShot"+ Count + "";
then above syntex error is coming.
Rama,
ReplyDeleteNo, copy the results in an excel graph manually or extract the results and create an excel for creating graphs.
Hello Bharath,
ReplyDeleteScreenshot functionality is working fine on my local machine. But when I deploy it on my HUB machine(Linux machine) and execute it through HUDSON then it is not working and below error found in Hudson console:
[testng] java.awt.AWTException: headless environment
[testng] at java.awt.Robot.(Robot.java:75)
[testng] at fbTAF.TestNGCustom.ScreenShot(TestNGCustom.java:74)
[testng] at fbTAF.TestNGCustom.onTestSuccess(TestNGCustom.java:38)
[testng] at org.testng.internal.Invoker.runTestListeners(Invoker.java:1800)
[testng] at org.testng.internal.Invoker.runTestListeners(Invoker.java:1780)
[testng] at org.testng.internal.Invoker.invokeMethod(Invoker.java:749)
[testng] at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:846)
[testng] at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1170)
[testng] at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
[testng] at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
[testng] at org.testng.TestRunner.runWorkers(TestRunner.java:1147)
[testng] at org.testng.TestRunner.privateRun(TestRunner.java:749)
[testng] at org.testng.TestRunner.run(TestRunner.java:600)
[testng] at org.testng.SuiteRunner.runTest(SuiteRunner.java:317)
[testng] at org.testng.SuiteRunner.access$000(SuiteRunner.java:34)
[testng] at org.testng.SuiteRunner$SuiteWorker.run(SuiteRunner.java:351)
[testng] at org.testng.internal.thread.ThreadUtil$CountDownLatchedRunnable.run(ThreadUtil.java:147)
[testng] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
[testng] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
[testng] at java.lang.Thread.run(Thread.java:662)
[testng] /var/lib/hudson/jobs/FBIB_TAF/workspace\ScreenShots\14_Mar_2012__08_56_56AM_127.0.0.1.png
I am using Selenium-grid-1.0.8 and RC machine is WIN7 having Firefox browser. My RC machine IP is 192.168.1.164 but InetAddress ownIP=InetAddress.getLocalHost(); return 127.0.0.1 as shown in above log.
Please help me in resolving this issue.
Thanks for information!
ReplyDeleteBHARATH MARRIVADA
Hello,
ReplyDeleteI ran the same scenario but unable to embed the hyperlink to the index.html report generated in old folder of test-output folder
It just shows it as text
Reporter output
[a href="C:\Projects\TestArtifact-2tr\Failure_ScreenShots\testSclGrp_TopRecentNews_01_Aug_2012__11_34_07AM.png",target='_blank']ScreenShot1[/a]
Please take a look and provide your comments
String NewFileNamePath;
Deletejava.awt.Dimension resolution = Toolkit.getDefaultToolkit()
.getScreenSize();
Rectangle rectangle = new Rectangle(resolution);
// 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(
"MMM_dd_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\\"
+ TestCaseId + "___" + dateFormat.format(date) + "_"
+ ownIP.getHostAddress() + ".png";
Print(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(
rectangle));
ImageIO.write(bi, "png", new File(NewFileNamePath));
NewFileNamePath = "ScreenShot"
+ "";
// Place the reference in TestNG web report
Reporter.log(NewFileNamePath);
Wait(3000);
HI Bharat,
DeleteI could not understand your response, can you please elaborate..??
In my post some of the html content was not copied properly(It is not allowing to past certain tags due to conflicts), so I have copied the latest code from my machine. Try to execute this code, hope this will resolve the issue.
DeleteHi Bharat,
DeleteThanks for taking out time and responding to my queries, but still no success
Not getting hyperlink, shows only text
Can you please provide your email id, so that I can share you my detailed code (or you can share your's as undersigned)
Thanking You
Somesh bansal
sbansal.ece@gmail.com
Hyper link is generated using following code.
DeleteNewFileNamePath = "ScreenShot" + "";
Reporter.log(NewFileNamePath);
Check whether the file really getting created in the designated path (NewFileNamePath)
my bad luck :(
ReplyDeleteunable to make out where I am making mistake
I have sent you an email, now it should work fine.
Deleteplease mail me the stuff since am also facing the same issue faced by Somesh Bansal
DeleteThanks alot for this post. I had followed your code for taking screenshot.For me ,screenshot is getting loaded in ScreenShots folder in my workspace. But I am unable to make it as a link in Testng-XSLT report.Could you please clarify my doubt.
ReplyDeleteIn Testng-XSLT, ReporterOutput page,only text is printed as "Screenshot"
Hi Bharath,
ReplyDeleteThe problem with above code is , it captures the screenshot of whatever application I am working on.This makes me unable to continue with my other work ,with selenium running in other window.
Also I guess the code You used to generate the Hyperlink will not work without using href.
Hello Rakesh,
DeleteI think there is an issue with TestNG wile parsing the escape sequence.
Look at following link for more details.
https://groups.google.com/forum/?fromgroups=#!topic/testng-users/9iIn-8kiYAo
The problem with thiscode is , it captures the screenshot of whatever application I am working on.This makes me unable to continue with my other work
ReplyDeleteunable to continue with my other work ???
DeleteWhy you are not able to continue with your work?
It silently take the screen shot of the entire desktop and store it in a file. If your application is minimized, you will get desktop screen shot.
Hi,
Deletethank you for posting such a beautiful concept !!!!!!!!
I tried same concept, for me 'Snapshot1' link also coming but problem is , if i click that link i am unable to see snapshot.
Its coming like this
"The page cannot be found
The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.
--------------------------------------------------------------------------------
Please try the following:
If you typed the page address in the Address bar, make sure that it is spelled correctly.
Open the draft.blogger.com home page, and then look for links to the information you want.
Click the Back button to try another link.
Click Search to look for information on the Internet.
HTTP 404 - File not found
Internet Explorer "
Please guide me how to over come this issue .....
Thanks
Sangeeta Mohnaty
I think there is an issue with TestNG wile parsing the escape sequence.
DeleteLook at following link for more details.
https://groups.google.com/forum/?fromgroups=#!topic/testng-users/9iIn-8kiYAo
public class TestListenerAdapter implements ITestListener {
ReplyDeleteprivate int Count = 0;
public void onFinish(ITestContext result) {}
public void onStart(ITestContext result) {}
@Override
public void onTestFailure(ITestResult result) {
System.out.println("Finished Executing Test: "+result.getName()+"Status: Failed"+"\n Reason:"+result.getThrowable());
try {
screenshot(result);
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onTestSkipped(ITestResult result) {
System.out.println("Skipped test: "+result.getName()+"Reason:"+result.getThrowable());
}
@Override
public void onTestStart(ITestResult result) {
System.out.println("Starting Test: "+result.getName());
}
@Override
public void onTestSuccess(ITestResult result) {
System.out.println("Finished Executing Test: "+result.getName()+"Status: Success.");
}
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
System.out.println("Test failed but within success percentage");
try {
screenshot(result);
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void screenshot(ITestResult result) throws AWTException{
try {
Calendar calendar = Calendar.getInstance();
String screenShotsFolder ="E:\\Programming\\eclipse-java-indigo-win32-andriod" +
"\\Eclipse Workspace\\Test Datamoat Web Apps\\test-output\\ScreenShots\\";
String testMethodAndTestClass = result.getMethod().getMethodName() + "(" + result.getTestClass().getName() + ")";
String filename = screenShotsFolder
+ testMethodAndTestClass + "-"
+ calendar.get(Calendar.YEAR) + "-"
+ calendar.get(Calendar.MONTH) + "-"
+ calendar.get(Calendar.DAY_OF_MONTH) + "-"
+ calendar.get(Calendar.HOUR_OF_DAY) + "-"
+ calendar.get(Calendar.MINUTE) + "-"
+ calendar.get(Calendar.SECOND) + "-"
+ calendar.get(Calendar.MILLISECOND)
+ ".png";
//Take Scrrenshot
File scrnsht =((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//Copy screenshot into a specific location
FileUtils.copyFile(scrnsht, new File(filename));
//Reporter.log("result");
//Place the reference in TestNG web report
Reporter.log(filename);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
But it does not working . Actually i did not get any screen shot in the location
can any one help me?
NewFileNamePath = "ScreenShot"+ Count + "";
ReplyDeleteReporter.log(NewFileNamePath);
by using this code i not able to see the link in testng reported created