In a TestNG Selenium framework, capturing screenshots in the event of a test failure is essential for debugging and understanding why a test case failed. Screenshots provide visual evidence of the application state at the time of failure, which is extremely helpful in tracking down issues. Here’s a step-by-step guide to capturing screenshots on test failure using TestNG and Selenium WebDriver:
Disclaimer: For QA-Testing Jobs, WhatsApp us @ 91-6232667387
Step 1: Set Up a Utility Method for Taking Screenshots
To capture screenshots in Selenium, you can create a utility method that handles the screenshot-taking process. The TakesScreenshot interface in Selenium WebDriver enables you to capture screenshots.
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ScreenshotUtil {
public static void captureScreenshot(WebDriver driver, String screenshotName) {
// Generate a timestamped filename to avoid overwriting previous screenshots
String timestamp = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
String fileName = screenshotName + "_" + timestamp + ".png";
// Take the screenshot and store it as a file
File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
try {
// Define the destination path and copy the file
FileUtils.copyFile(srcFile, new File("./screenshots/" + fileName));
System.out.println("Screenshot saved as " + fileName);
} catch (IOException e) {
System.out.println("Failed to save screenshot: " + e.getMessage());
}
}
}
In this utility class, captureScreenshot() takes a screenshot and saves it to a directory, including a timestamp in the filename to make it unique. Using FileUtils from Apache Commons IO makes it easy to copy the screenshot file to a specified directory.
Step 2: Implement an ITestListener to Capture Screenshots on Test Failure
TestNG provides the ITestListener interface, which has methods that are invoked at different stages of a test’s lifecycle. Implementing this interface allows you to define custom actions, such as taking screenshots, when tests fail.
Here's how you can implement the listener:
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.openqa.selenium.WebDriver;
public class TestListener implements ITestListener {
private WebDriver driver;
// Constructor to receive WebDriver instance
public TestListener(WebDriver driver) {
this.driver = driver;
}
@Override
public void onTestFailure(ITestResult result) {
// Capture the test method name for the screenshot file
String testMethodName = result.getName();
ScreenshotUtil.captureScreenshot(driver, testMethodName);
}
@Override
public void onTestStart(ITestResult result) {}
@Override
public void onTestSuccess(ITestResult result) {}
@Override
public void onTestSkipped(ITestResult result) {}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
@Override
public void onStart(ITestContext context) {}
@Override
public void onFinish(ITestContext context) {}
}
In the onTestFailure() method, the ITestResult parameter allows you to get details about the test method, such as its name, which you can use for naming the screenshot file. The screenshot is taken only when the test fails.
Step 3: Configure TestNG to Use the Listener
To activate the listener, you can configure it in your TestNG XML file or directly in the test class.
Option 1: Configure the Listener in the TestNG XML File
Add the following configuration to your testng.xml file:
<listener class-name="your.package.TestListener" />
</listeners>
Option 2: Use @Listeners Annotation in Your Test Class
Alternatively, you can use the @Listeners annotation in your test classes:
import org.testng.annotations.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
@Listeners(TestListener.class)
public class SampleTest {
WebDriver driver;
@Test
public void testMethodThatFails() {
// Set up WebDriver and test
driver = new ChromeDriver();
driver.get("https://example.com");
// Simulate a test failure
assert driver.getTitle().equals("Non-Existent Title");
}
}
In this example, if testMethodThatFails fails, TestListener will automatically capture a screenshot using the onTestFailure() method.
Step 4: Organize and View the Screenshots
Screenshots are saved in the ./screenshots/ directory with a timestamped filename for each failure. This organization helps you easily locate screenshots and correlate them with specific test cases.
Additional Tips
- Parallel Testing: If you’re running tests in parallel, ensure that the screenshot filenames are unique (by including timestamps or thread IDs) to avoid overwriting.
- Reporting Integration: Integrate screenshots into reports like ExtentReports or Allure. This allows easy access to screenshots from within the test report.
- Screenshot Cleanup: Periodically clean up old screenshots, as they can accumulate over time and consume storage space.
Summary
To capture a screenshot on test failure in a TestNG Selenium framework:
- Create a utility method for capturing screenshots.
- Implement the ITestListener interface to take screenshots on test failure.
- Configure the listener in TestNG or directly in the test classes.
This approach provides a flexible, reusable way to capture screenshots whenever a test fails, improving debugging efficiency and enabling better insight into issues during automated test runs.