Advance Level Screenshot capturing using Selenium WebDriver and TestNG Listners

In my opinion, you should avoid the following:
  • using static drivers (because using static variables is a bad practice)
  • using static methods for taking screenshots (because using static methods is a bad practice)
  • taking screenshots in the test methods (because you will duplicate code in lots of tests)
  • taking screenshots in the @After methods (because you dont need to do this)
I prefer to take the screenshots using a TestNG listener as follows.
  1. create a class for taking the screenshots
Every time you need to take a screenshot, create an object for this class and use the capture method.
The capture method will take the screenshot and save it in the screenshots folder.
  1. package framework;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import org.openqa.selenium.OutputType;
  5. import org.openqa.selenium.TakesScreenshot;
  6. import org.openqa.selenium.WebDriver;
  7.  
  8. public class Screenshot {
  9. private WebDriver driver;
  10. private final String folderPath = "./src/test/resources/screenshots/";
  11. public Screenshot(WebDriver driver) {
  12. this.driver = driver;
  13. validateFolderExists();
  14. }
  15. private void validateFolderExists() {
  16. File folder = new File(folderPath);
  17. if (!folder.exists())
  18. folder.mkdir();
  19. }
  20. public void capture(String fileName) {
  21. try {
  22. String name = folderPath + fileName + ".png";
  23. FileOutputStream file = new FileOutputStream(name);
  24. file.write(
  25. ((TakesScreenshot) driver)
  26. .getScreenshotAs(OutputType.BYTES));
  27. file.close();
  28. }
  29. catch (Exception ex) {
  30. throw new RuntimeException("cannot create screenshot;", ex);
  31. }
  32. }
  33. }

2. Create a TestNG listener that takes the screenshot if the test method fails or is skipped
The listener gets the driver object from the test class through reflection.
  1. package framework;
  2. import java.lang.reflect.Field;
  3. import org.openqa.selenium.WebDriver;
  4. import org.testng.ITestContext;
  5. import org.testng.ITestListener;
  6. import org.testng.ITestResult;
  7. import org.testng.Reporter;
  8. import framework.BrowserDriver;
  9. import framework.Screenshot;
  10. public class CustomTestListener implements ITestListener {
  11. @Override
  12. public void onTestFailure(ITestResult result) {
  13. String fileName = "failed_" + result.getName();
  14. new Screenshot(driver(result)).capture(fileName);
  15. }
  16. @Override
  17. public void onTestSkipped(ITestResult result) {
  18. String fileName = "skipped_" + result.getName();
  19. new Screenshot(driver(result)).capture(fileName);
  20. }
  21.  
  22. @SuppressWarnings("unchecked")
  23. private WebDriver driver(ITestResult testResult)
  24. {
  25. BrowserDriver browserDriver = null;
  26. try {
  27. Classextends ITestResult> testClass =
  28. (Class extends ITestResult>)
  29. testResult.getInstance().getClass();
  30.  
  31. Field driverField = testClass.getDeclaredField("driver");
  32. browserDriver = (BrowserDriver)driverField
  33. .get(testResult.getInstance());
  34. }
  35. catch (SecurityException |
  36. NoSuchFieldException |
  37. IllegalArgumentException |
  38. IllegalAccessException e) {
  39.  
  40. throw new RuntimeException(
  41. "couldnt get the driver from the test class!");
  42. }
  43. return browserDriver.wrappedDriver();
  44. }
  45. @Override
  46. public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
  47. }
  48.  
  49. @Override
  50. public void onStart(ITestContext context) {
  51. }
  52. @Override
  53. public void onFinish(ITestContext context) {
  54. }
  55.  
  56. @Override
  57. public void onTestStart(ITestResult result) {
  58. }
  59.  
  60. @Override
  61. public void onTestSuccess(ITestResult result) {
  62. }
  63. }

3. add the listener to the test class using the Listener annotation
  1. @Listeners(CustomTestListener.class)
  2. public class SiteTests {
  3. public BrowserDriver driver;
  4. …………………………………..

Advantages of this approach:
  1. no static driver
  2. no static methods for taking the screenshot
  3. no “take screenshot” code in the test methods
  4. no “take screenshot” code in the @After methods
Disadvantages:
  1. using reflection to get the driver; complicated code for this purpose
  2. using null in the test listener

GUEST AUTHOR

Alex Siminiuc

Follow Us

YouTube Channel | Facebook Page | Telegram Channel | Quora Space
Feel free to ask queries or share your thoughts in comments or email us.

Comments

Popular posts from this blog

10+ Best Demo Websites for Selenium Automation Testing Practice

Automate Amazon like E-Commerce Website with Selenium WebDriver

Handle Static and Dynamic Web Table in Selenium WebDriver

How to Automate Google Search with Selenium WebDriver

Top 7 Web Development Trends in 2022

25+ Most Important Selenium WebDriver Commands Tutorial

50+ Most Important Selenium WebDriver Interview Questions and Answers

How to Find Broken Links on Webpage with Selenium WebDriver