Taking ScreenShot ONLY for Failed Tests

We have discussed about simple way of taking a screen shot earlier. Now in this tutorial, we will see how to take screen shot ONLY for failed tests.

To do this, first we need to create a class and then implement TestNG 'ITestListener'. We will have a method called 'onTestFailure'. We need to add the code to take the screen shot in this method. Instead of just taking the screen shot, we will get the Test method name and take a screen shot with test name and place it is destination folder.

How to get the driver object in the TestListener class using TestNG?

To take a screenshot in Selenium, we need to to have a driver object. We can get the driver from the ITestContext (this should be set in the base setup where we create our driver instance)

NOTE: - If you are using latest version of selenium, please check this updated article Take Screenshot using FileHandler class

package com.pack.listeners;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import com.pack.sample.TestBase;

public class TestListener implements ITestListener {
	WebDriver driver=null;
	String filePath = "D:\\SCREENSHOTS";
    @Override
    public void onTestFailure(ITestResult result) {
    	System.out.println("***** Error "+result.getName()+" test has failed *****");
    	String methodName=result.getName().toString().trim();
        ITestContext context = result.getTestContext();
       WebDriver driver = (WebDriver)context.getAttribute("driver");
    	takeScreenShot(methodName, driver);
    }
    
    public void takeScreenShot(String methodName, WebDriver driver) {
    	 File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
         //The below method will save the screen shot in d drive with test method name 
            try {
				FileUtils.copyFile(scrFile, new File(filePath+methodName+".png"));
				System.out.println("***Placed screen shot in "+filePath+" ***");
			} catch (IOException e) {
				e.printStackTrace();
			}
    }
	public void onFinish(ITestContext context) {}
  
    public void onTestStart(ITestResult result) {   }
  
    public void onTestSuccess(ITestResult result) {   }

    public void onTestSkipped(ITestResult result) {   }

    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {   }

    public void onStart(ITestContext context) {   }
}  

Before executing the above program, we need to add TestListener class in testng.xml file as below:

<listeners>
       <listener class-name="com.pack.listeners.TestListener"/>
  </listeners>

In the Next tutorial, we will try to extend the way of taking the screen shot and placing it by creating a folder with Test Class name and Screens shots of that particular test class as shown in below screen shot. Click here for example on Take Screenshot and place it in a folder with Test Class name

TestNG Scrennshots folder

Test Frameworks: 

Comments

I have two questions:
I don't understand where this is being imported from: import com.pack.sample.TestBase;

Also, is it possible to make the screenshot path dynamic to maybe be set via a parameter so the listener can be reused and the test can save the screenshot to a specific location?

Thanks!

First you need to get the driver, there are multiple ways in getting the driver. Above one is just an example

Second, yes we should always set a dynamic path using file Separator, and we also need to make sure that works in different Os windows/mac etc.

Hi, TestBase class has been imported to call function with name getDriver() which would return driver initialization. Yes you can set screenshot location dymanic by simply passing a string in method and call string in your test script.

Here you have specified you need to get the driver, but how it will be done??

I have implemented the listener as above for taking screenshots for failed tests, but when i am working with parallel tests
ex: parallel="tests" thread-count="2"
and i have 2 tests both are going to fail, then my Listener is failed to take screen shots, it also not able to close the browser for one of the test.
If i run it thread-count="1" then it is working fine and taking failed screenshots for both the tests.

please suggest me the solution???

I have implemented parameterized testing , i am running same tests in different browsers using test suite . Screenshot taking is working fine but the problem is if test fails in any one of the browser , how to get browser name in the screenshot so that it would be easy to understand .

if it fails in multiple browsers same screenshot is overwritten since same method is failed in both the browsers .

can you please tell me a workaround for this .... ?

I have implemented parameterized testing , i am running same tests in different browsers using test suite . Screenshot taking is working fine but the problem is if test fails in any one of the browser , how to get browser name in the screenshot so that it would be easy to understand .

if it fails in multiple browsers same screenshot is overwritten since same method is failed in both the browsers .

can you please tell me a workaround for this .... ?

The code above implies getDriver() is a static method, but that's usual an instance method that returns the current browser. Any suggestions on how to grab that?

thanks for help

Can we screenshot element that cause failure in onTestFailure?
Thanks

Add new comment

CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.