Open In App

How to Capture Screenshot for Failed Tests in TestNG?

Last Updated : 04 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Capturing screenshots for failed tests in TestNG is a crucial practice for effective test automation and debugging. When running automated tests using Selenium WebDriver with TestNG, capturing visual evidence of failures is essential to understand what went wrong. By implementing TestNG listeners, you can automatically capture screenshots whenever a test fails, allowing you to identify and address issues quickly.

In this guide, we'll walk through the steps to capture screenshots of failed tests using TestNG.

Steps to capture screenshots using Selenium and TestNG Listener

  • Step 1. Create a Maven project by typing the following command in your terminal. This will create a " my-app " folder containing the project structure and pom.xml file. You can change the project name, and GroupID (com.mycompany.app in this case) to your choice.

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

The project folder will look like this:

folderstructure
Folder Structure
  • Step 2. Add the following maven dependencies in pom.xml file:
XML
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.23.0</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.10.2</version>
    <scope>test</scope>
</dependency>
  • Step 3. After modifying the pom.xml file, install the added dependencies by running the command inside your project folder

mvn install

  • Step 4. In order to run the browser using Selenium, we require a driver file which is unique to the browser. Download the respective driver file for your browser, browser version (browser version and driver version should match), OS and Architecture by using the below table as a guide. You will download a zip file. Extract it to a location of your choice (we have extracted it at C:\Drivers folder).

Browser name

Driver name

Link

Google Chrome

chromedriver.exe

https://googlechromelabs.github.io/chrome-for-testing/

Mozilla Firefox

geckodriver.exe

https://github.com/mozilla/geckodriver/releases

Microsoft Edge

edgedriver.exe

https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver

We are using Google chrome in this tutorial, but we also have mentioned the necessary changes to the code to capture screenshot with browser of your choice.

  • Step 5. Create a java class named "AppListener" which implements the "ITestListeners" interface provided by TestNG module inside the test/java folder of our project. This interface contains many methods such as onTestStart(), onTestSuccess(), onTestFailure(), etc. which can be implemented with our custom logic to run our code at certain stages of the test case being run.
Java
package com.mycompany.app;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.io.FileHandler;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import java.io.File;
import java.io.IOException;

public class AppListener implements ITestListener{

    @Override
    public void onTestSuccess(ITestResult result) {
        System.out.println("Test passed!");
    }

    @Override
    public void onTestFailure(ITestResult result) {
        File srcFile = ((TakesScreenshot) AppTest.driver).getScreenshotAs(OutputType.FILE);
        File destFile = new File("failure.png");

        try {
            FileHandler.copy(srcFile, destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStart(ITestContext context) {
        System.setProperty("webdriver.chrome.driver", "C:\\Drivers\\chromedriver.exe");
    }

    @Override
    public void onFinish(ITestContext context) {
        System.out.println("Finished all test cases.");
        if (AppTest.driver != null) {
            AppTest.driver.quit();
        }
    }
    
}

This is a Listener class which will be given to our actual test class in the form of annotation. When our test class begin to run, the onStart() method is called from this listener class. Inside the test class there will be multiple test cases (methods). When an individual test method succeeds i.e. no exception is thrown, then the onTestSuccess() method is called. If the test case fails i.e. some kind of exception is thrown, then onTestFailure() method is called. After running all the test cases, the onFinish() method is called finally.

Step 6. Create a new java file or add your tests to already existing AppTest.java file inside the test/java/com.mycompany.app

Java
package com.mycompany.app;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import java.io.IOException;

 @Listeners(AppListener.class)
public class AppTest {

    static ChromeOptions options = new ChromeOptions().addArguments("--headless").addArguments("--disable-gpu").addArguments("--window-size=1920,1080");
    static WebDriver driver = new ChromeDriver(options);

    @Test
    public void test1() {
        driver.get("https://www.mozilla.org");
        System.out.println("Page title is: " + driver.getTitle());
        int statusCode = getHttpStatusCode("https://www.mozilla.org");
        Assert.assertTrue(statusCode == 200, "URL is not accessible, Status Code: " + statusCode);
    }

    @Test
    public void test2() {
        driver.get("https://www.mozilla.org/about-us");
        System.out.println("Page title is: " + driver.getTitle());
        int statusCode = getHttpStatusCode("https://www.mozilla.org/about-us");
        Assert.assertTrue(statusCode == 200, "URL is not accessible, Status Code: " + statusCode);
    }
    private int getHttpStatusCode(String url) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(url);
            HttpResponse response = httpClient.execute(request);
            return response.getStatusLine().getStatusCode();
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }
}

We have created a custom method to get the status code of the site using Apache HTTP components since many of websites handle the page not found error by creating a custom page. We are running two test cases: one test case tries to visit a valid website, and another tries to visit an invalid website. Hence, we take the screenshot of the error page of bad URL.

If you want to use Firefox or Edge browser instead of Chrome just replace:

Driver Class

Property Name

Import Statement

ChromeDriver()

webdriver.chrome.driver

import org.openqa.selenium.chrome.ChromeDriver

FirefoxDriver()

webdriver.gecko.driver

import org.openqa.selenium.firefox.FirefoxDriver

EdgeDriver()

webdriver.edge.driver

import org.openqa.selenium.edge.EdgeDriver

Also, make sure you are copying the correct path of the driver for specific browser, instead of using a single driver for all browsers.

Output:

Here are the PNG file which is generates in the testoutput

Output-Image
Output Image

The above video showcases that one of the two test cases failed triggering a screenshot of the bad URL which we were trying to hit.

Conclusion

Capturing screenshots for failed tests in TestNG enhances your test automation process by providing clear and actionable visual evidence of test failures. Implementing a TestNG listener to handle screenshot capture is a straightforward yet powerful way to improve your test reporting and debugging capabilities. By following the steps outlined, you'll be able to integrate screenshot capture into your TestNG tests efficiently, ensuring you have the necessary information to resolve issues promptly and maintain high-quality software testing standards.


Next Article
Article Tags :

Similar Reads