How to take screenshots for failed tests using TestNG ?
Automated testing is a significant part of the entire software testing life cycle. The ability to execute scripts without interfering has resulted in higher efficiency. If something goes wrong and test script fails, some visual representation of exact anomaly helps tester to identify the issue. This is where Selenium screenshots come into play.
Automation test script may fail due to various problems:
· Application issue
· Assertion failure
· Not able to find web elements on a page
· Timeout while finding web elements on a page
To capture screenshot of the test cases that has been failed, TestNG provides Listeners, an interface that modifies TestNG behavior. Listeners are implemented by ITestListener interface. As the name suggests, Listeners “listen” to the events defined in Selenium script and behave accordingly. When the test case fails, it is redirected to the new block written for screenshot.
Here are steps to capture screenshot in Selenium using TestNG Listener:
· Create a class. Implement TestNG ‘ITestListener’.
· Call the method ‘onTestFailure’.
· Add the code to take a screenshot with this method.
Sample code to capture screenshot of failed test case is shown below:
Pre-requisite: Create a maven project and add following dependencies to pom.xml.
Step 1 - Create a base class to define a webdriver instance and a method to take the screenshot.
By using TakesScreenshot and getScreenshotAs methods, we can take screenshot.
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
(TakesScreenshot)driver (As we can’t create object directly, so typecast it) and then get screenshot as file and assign it to the File variable.
FileUtils.copyFile(srcFile, new File("./Screenshots/"+ testMethodName + "_" + TimeStamp + ".png"));
Instead of just taking a screenshot, we will get the test method name, timestamp and screenshot and store it into a destination folder.
To get the timestamp, we will use a class in java called as Date. Let's create an object of this class.
Date d = new Date();
It will return current system date along with time, but here we have to replace ”:” and “ ” because they are not supported in the file name. So will replace ”:” and “ ” and convert this timestamp to String.
String TimeStamp = d.toString().replace(":", "_").replace(" ", "_");
Step 2 - Create a TestNG Listener and call “onTestFailure” method.
Code snippet to create a class “TestStatusListener” and implement ITestListener:
In the above code, ITestResult is an interface which keeps all information about test case like test case name, test case execution status. When a test script fails, it calls a method onTestFailure (method FailedScreenshot() from a Base class) to take screenshot.
Step 3 – Create another class “Testcases”.
Step 4 – Implement TestNG Listener in our regular project class i.e. “Testcases”.
There are two different ways to connect class and interface.
The first way is to use Listener annotation (@Listeners) as shown below:
We will use this in the class “Testcases” as shown below:
Step 5 – Execute the “Testcases” class. onTestFailure method in class “TestStatusListener” is called automatically when any method annotated as @Test fails.
Output of the project class "Testcases" on console looks like:
“ScreenshotTest2” failed on asserting title of the webpage. Screenshot is captured for this method under “Screenshots” folder. Screenshot file name contains failed method name and timestamp.
Step 6 – Use of Listener for multiple classes
If project has multiple classes, instead of adding Listeners to each class, create a testng.xml and add listeners tag in xml.
This listener is implemented throughout the test suite irrespective of the number of classes you have. When you run this XML file, listeners will work on all classes mentioned in testng.xml.
Listeners are interfaces used in selenium web driver script.
Demonstrated the use of ITestListener with onTestFailure method to take screenshots of only failed test cases.
Implemented the Listeners for single class with @Listeners annotation
Implemented the Listeners for multiple classes with <listener> tag in testng.xml.
Happy Testing !