Capture screenshot when TestNG Test method fails - Explore Selenium

Explore Selenium

Selenium Automation

Automation, Selenium, TestNG

Capture screenshot when TestNG Test method fails

When  a test fails during the execution, for reference we should capture screenshot, so that debugging the failures are easy. How to capture screenshot when TestNG  Test method is failed and logic to prepare name and storage path  are explained in this post.

Following are the two main steps to get this.

  1. Provide implementation for “onTestFailure” method of “ITestListener”.
  2. Define implemented listener in testng.xml file
1. Provide Implementation for “onTestFailure” method
  • We can achieve this by using ITestListener. Listeners are used to change the behavior of TestNG.
  • ITestListener is an Interface, it has a method “onTestFailure” which will be called when test method fails.
  • If we use ITestListener directly, we should provide the implementations to all the methods, so to overcome this, use “TestListenerAdapter”
  • TestListenerAdapter implements ITestListener with empty methods, so no need to provide the implementation to all the methods that are not used.
  • Below is the code to take the screenshot, name and path of it for storage
    • It has method onTestFailure() where we get the name of the test class and test method and then prepare the path to store the screenshot.
      • Create a directory “LatestResults” inside “screenshots” if not existed.
      • Create a directory with Test class name inside the LatestResults.
      • Here is the directory created after execution Screenshot path and name
    • In the below code, used  captureScreenshot(), this method will take the screenshot by using WebDriver api’s, save that screenshot with name as test method name and then return that name.
  • package com.exploreselenium.listeners;
    
    import com.exploreselenium.ScreenshotInResultsTest;
    import org.apache.commons.io.FileUtils;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    import org.openqa.selenium.WebDriver;
    import org.testng.ITestResult;
    import org.testng.Reporter;
    import org.testng.TestListenerAdapter;
    import java.io.File;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    public class LocalScreenshot extends TestListenerAdapter {
    
        String Seperator=System.getProperty("file.separator");
    
        @Override
        public void onTestFailure(ITestResult result) {
            WebDriver driver = null;
            Reporter.setCurrentTestResult(result);
            String sTestClassName=result.getTestClass().getRealClass().getSimpleName();
            System.out.println("Test class name ..."+sTestClassName);
            String sFileName=result.getName();
            System.out.println("Test method name ..."+sFileName);
            driver= ScreenshotInResultsTest.gerDriverDetails(result.getTestClass().getName());
            String imagePathInHost="file:///"+System.getProperty("user.dir")+Seperator+"screenshots"+Seperator+"LatestResults"+Seperator+sTestClassName+Seperator+captureScreenshot(driver,sTestClassName,sFileName);
            System.out.println("Image path...."+imagePathInHost);
            Reporter.log("<a href=" + imagePathInHost + "> <img width='100' height='100' src=" + imagePathInHost + "> </a>");
            Reporter.setCurrentTestResult(null);
    
        }
    
        public String captureScreenshot(WebDriver driver,String sTestClassName,String sFileName)
        {
            sFileName=sFileName+".png";
            try
            {
                File file = new File("screenshots" + Seperator + "LatestResults");
                if (!file.exists())
                {
                    System.out.println("File created somewhere" + file);
                    file.mkdir();
                }
    
                File sourceFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
                File targetFile = new File("screenshots" + Seperator + "LatestResults" + Seperator + sTestClassName, sFileName);
                FileUtils.copyFile(sourceFile, targetFile);
                return sFileName;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
  • In the above code used Reporter test class as below, this will show the captured screenshot image in size 100X100 pixel in Reporter output section of index.html file in test-ouput directory.
  • Reporter.log("<a href=" + imagePathInHost + "> <img width='100' height='100' src=" + imagePathInHost + "> </a>");
    

    Here is the index.html file for the above test class.

Capture screenshot when test failed

2.  Define implemented listener in testng.xml file
  • Here is how we can define listeners in testng.xml
  • <suite>
     
      <listeners>
        <listener class-name="com.example.MyListener" />
        <listener class-name="com.example.MyMethodInterceptor" />
      </listeners>
     
    ...
    </suite>
    
  • Below is the testng.xml
  • <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Screenshot Test Suite" verbose="2">
        <listeners>
           <listener class-name='com.exploreselenium.listeners.LocalScreenshot' />
        </listeners>
    
        <test name="SampleTest1">
           <classes>
                <class name="com.exploreselenium.ScreenshotInResultsTest"></class>
            </classes>
    
        </test>
    
    </suite>
    
  • In above xml file used class “ScreenshotInResultTest”
    • It has two test methods and in each test method, used Assert.fail() to make failed the test methods.
    • It has BeforeClass and AfterClass to start and quit the driver.
  • Below is the complete code
  • package com.exploreselenium;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.testng.Assert;
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Test;
    
    import java.util.HashMap;
    
    
    public class ScreenshotInResultsTest {
    
        private static HashMap<String, WebDriver> driverObjMap=new HashMap<String, WebDriver>();
        WebDriver driver;
        @BeforeClass
        public void browserInstantiate(){
            System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\geckodriver.exe");
            driver=new FirefoxDriver();
            driverObjMap.put(getClass().getName(),driver);
            driver.manage().window().maximize();
            System.out.println("Browser Instantiated..");
        }
    
        @Test
        public void openFacebook(){
            driver.get("http://facebook.com");
            System.out.println("Facebook Opened ..");
            Assert.fail("Test was failed");
    
        }
    
        @Test
        public void openGoogle(){
            driver.get("http://google.com");
            System.out.println("Google Opened ..");
            Assert.fail("Test was failed");
    
        }
    
        public static WebDriver gerDriverDetails(String className){
            return driverObjMap.get(className);
        }
    
        public static HashMap<String, WebDriver> gerDriverObjMap(){
            return driverObjMap;
        }
    
        @AfterClass
        public void quitDriver(){
            if(gerDriverObjMap().get(getClass().getName())!=null){
                gerDriverObjMap().get(getClass().getName()).quit();
                gerDriverObjMap().remove(getClass().getName());
                System.out.println("driver for class : "+ getClass().getName() + "is closed");
            }
        }
    }
    

 When executed the above testng.xml, it will run these two test methods and  takes screenshots as mentioned above.

Summary: 

In this post, we learned

  • how to take the screenshot when test method is failed
  • how to use the listeners
  • how to show the captured screenshot in index.html file of TestNG generated test-output.
TestNG Test Groups
TestNG emailable report customization
0

12 Comments

  1. Sasidhar

    Thanks, your explanation is very clear and it is very useful for us.

  2. Anonymous

    Thank you, Very good explanation,

  3. Mohan krishna

    Thank you, very good explanation.

  4. job search

    I could not refrain from commenting. Exceptionally well written!

  5. business for sale

    We stumbled over here from a different web page and thought I may as well check things out. I like what I see so now i am following you. Look forward to going over your web page yet again.

  6. A round of applause for your blog article.Really looking forward to read more. Much obliged.

  7. Whither manual EQ mou

    “Great blog. Great.”

  8. I simply want to tell you that I am very new to blogging and site-building and actually enjoyed this page. Almost certainly I’m likely to bookmark your blog . You really have perfect articles and reviews. Thanks a lot for sharing your web site.

  9. Nikhil

    Can you explain how to use this while running a suite instead of a single test? Thanks.

    • MK

      Nikhil, It takes screenshot when test fails, this works while running the suite as well.
      I wrote the logic in test listener and this is used in suite level. so this works when you run the suite.

  10. eebest8 best

    “A big thank you for your blog article.Really looking forward to read more. Really Cool.”

  11. tim allen

    I want to get across my passion for your kindness in support of persons who actually need guidance on the niche. Your very own commitment to getting the solution all over appeared to be amazingly practical and has in most cases enabled those much like me to achieve their desired goals. Your new invaluable instruction entails so much to me and further more to my office workers. Warm regards; from everyone of us.

Leave a Reply