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

Quora Space | Facebook Page | Telegram Channel
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 Automation Testing Practice

Automate 'User Registration' of E-commerce Website using Selenium

Automate Browser Actions on Godaddy.com using Selenium

Selenium WebDriver Browser and Navigation Commands