ExtentTestExecutionListener

package com.mridul.software.automation.listeners;  
 import com.aventstack.extentreports.ExtentReports;  
 import com.aventstack.extentreports.ExtentTest;  
 import com.mridul.software.automation.aspects.webdriver.TakeScreenshotAspect;  
 import com.mridul.software.automation.rest.interceptors.ExtentLoggingClientHttpRequestInterceptor;  
 import com.mridul.software.automation.spring.context.AppPropertiesCtx;  
 import com.mridul.software.automation.spring.context.UtilsCtx;  
 import lombok.extern.slf4j.Slf4j;  
 import org.apache.commons.io.FileUtils;  
 import org.springframework.stereotype.Component;  
 import org.springframework.test.context.TestContext;  
 import org.springframework.test.context.support.AbstractTestExecutionListener;  
 import org.testng.ITestContext;  
 import org.testng.ITestResult;  
 import org.testng.Reporter;  
 import java.io.File;  
 import java.lang.reflect.Method;  
 import java.util.ArrayList;  
 import java.util.Base64;  
 import java.util.List;  
 import java.util.Set;  
 import java.util.stream.Collectors;  
 import static com.google.common.base.Preconditions.checkNotNull;  
 @Slf4j  
 @Component  
 public class ExtentTestExecutionListener extends AbstractTestExecutionListener {  
   private ExtentReports reports;  
   private AppPropertiesCtx config;  
   private UtilsCtx utilsCtx;  
   private ExtentTestEventListener extentTestEventListener;  
   private ExtentLoggingClientHttpRequestInterceptor interceptor;  
   private TakeScreenshotAspect takeScreenshotAspect;  
   private static final ThreadLocal<ExtentTest> TEST_THREAD_LOCAL = new ThreadLocal<>();  
   private void initialize(TestContext testContext) {  
     log.debug("Initializing spring beans for {}", this.getClass().getCanonicalName());  
     reports = explicitlyWireBean(testContext, ExtentReports.class);  
     config = explicitlyWireBean(testContext, AppPropertiesCtx.class);  
     utilsCtx = explicitlyWireBean(testContext, UtilsCtx.class);  
     extentTestEventListener = explicitlyWireBean(testContext, ExtentTestEventListener.class);  
     interceptor = explicitlyWireBean(testContext, ExtentLoggingClientHttpRequestInterceptor.class);  
     takeScreenshotAspect = explicitlyWireBean(testContext, TakeScreenshotAspect.class);  
     log.debug("reports : {} and config : {}", reports, config);  
     checkNotNull(reports, "reports not autowired!");  
     checkNotNull(config, "config not autowired!");  
     deleteScreenshotPath();  
   }  
   private <T> T explicitlyWireBean(TestContext testContext, Class<T> clazz) {  
     return testContext.getApplicationContext().getBean(clazz);  
   }  
   private enum TestLevel {  
     CLASS,  
     METHOD,  
     EXECUTION  
   }  
   private void initializeExtentTest(TestContext testContext, TestLevel testLevel) {  
     log.debug("Initializing the initializeExtentTest!");  
     checkNotNull(reports, "reports not autowired!");  
     ExtentTest test = null;  
     switch (testLevel) {  
       case CLASS:  
         test = reports.createTest("beforeTestClass");  
         break;  
       case METHOD:  
         test = reports.createTest(testContext.getTestClass().getName());  
         break;  
       case EXECUTION:  
         test = reports.createTest(testContext.getTestMethod().getName());  
         break;  
       default:  
         throw new UnsupportedOperationException("test is not created!");  
     }  
     checkNotNull(test, "test is not created!");  
     TEST_THREAD_LOCAL.set(test);  
   }  
   private void setExtentTest() {  
     extentTestEventListener.setExtentTest(TEST_THREAD_LOCAL.get());  
     interceptor.setExtentTest(TEST_THREAD_LOCAL.get());  
   }  
   private void addTestNameToScreenshotPath(TestContext testContext) {  
     String screenshotPath = config.getReport().getScreenshot().getFilePath();  
     String pathWithTestMethodName = screenshotPath + testContext.getTestMethod().getName() + File.separator;  
     config.getReport().getScreenshot().getTest().setMethodName(pathWithTestMethodName);  
   }  
   private void deleteScreenshotPath() {  
     String screenshotPath = config.getReport().getScreenshot().getFilePath();  
     utilsCtx.getFileSystemUtils().deleteFileIfExists(screenshotPath);  
   }  
   @Override  
   public void beforeTestClass(TestContext testContext) {  
     log.debug("Initializing test context beforeTestClass!");  
     initialize(testContext);  
   }  
   @Override  
   public void beforeTestMethod(TestContext testContext) {  
     log.debug("Initializing extent test beforeTestMethod!");  
   }  
   @Override  
   public void beforeTestExecution(TestContext testContext) {  
     log.debug("Initializing extent test beforeTestExecution!");  
     this.initializeExtentTest(testContext, TestLevel.EXECUTION);  
     setExtentTest();  
     addTestNameToScreenshotPath(testContext);  
   }  
   @Override  
   public void afterTestExecution(TestContext testContext) {  
     log.debug("Empty override");  
   }  
   @Override  
   public void afterTestMethod(TestContext testContext) {  
     log.debug("invoking after test!");  
     List<ITestResult> currentTestResult = getCorrespondingResultFor(testContext.getTestMethod());  
     currentTestResult.forEach(this::reportOnStatus);  
     log.debug("Flushing extent reports!");  
     reports.flush();  
   }  
   private List<ITestResult> getCorrespondingResultFor(Method method) {  
     ITestContext context = Reporter.getCurrentTestResult().getTestContext();  
     List<ITestResult> allResults = new ArrayList<>();  
     allResults.addAll(context.getPassedTests().getAllResults());  
     allResults.addAll(context.getFailedTests().getAllResults());  
     allResults.addAll(context.getSkippedTests().getAllResults());  
     clearRetrievedTests(context);  
     return allResults  
         .stream()  
         .filter(result -> result.getMethod().getConstructorOrMethod().getMethod().equals(method))  
         .collect(Collectors.toList());  
   }  
   private void clearRetrievedTests(ITestContext context) {  
     context.getPassedTests().getAllResults().clear();  
     context.getFailedTests().getAllResults().clear();  
     context.getSkippedTests().getAllResults().clear();  
   }  
   private void reportOnStatus(ITestResult currentTestResult) {  
     switch (currentTestResult.getStatus()) {  
       case 1:  
         onTestSuccess(currentTestResult);  
         break;  
       case 2:  
         onTestFailure(currentTestResult);  
         break;  
       case 3:  
         onTestSkipped(currentTestResult);  
         break;  
       default:  
         throw new UnsupportedOperationException(  
             "TestAgent result with status : " + currentTestResult.getStatus() + " is unsupported!");  
     }  
   }  
   //not testNg method  
   private void onTestSuccess(ITestResult result) {  
     log.debug("Initializing on test success!");  
     String successMessage = config.getMessage().getSuccessMessage().replace("{}", result.getName());  
     addScreenshotToTestIfEnabled(TEST_THREAD_LOCAL.get(), isScreenshotEnabled())  
         .pass(successMessage);  
   }  
   //not testNg method  
   private void onTestFailure(ITestResult result) {  
     log.debug("Initializing on test failure!");  
     String failureMessage = config.getMessage().getFailureMessage().replace("{}", result.getName());  
     addScreenshotToTestIfEnabled(TEST_THREAD_LOCAL.get(),  
         (isScreenshotEnabledForFailure() || isScreenshotEnabled()))  
         .fail(failureMessage + System.lineSeparator() + result.getThrowable());  
   }  
   //not testNg method  
   private void onTestSkipped(ITestResult result) {  
     log.debug("Initializing on test skipped!");  
     String skippedMessage = config.getMessage().getSkippedMessage().replace("{}", result.getName());  
     addScreenshotToTestIfEnabled(TEST_THREAD_LOCAL.get(), isScreenshotEnabled())  
         .skip(skippedMessage + System.lineSeparator() + result.getThrowable());  
   }  
   private boolean isScreenshotEnabled() {  
     if (takeScreenshotAspect.getScreenshotNames().isEmpty()) {  
       return false;  
     }  
     return config.getReport().getScreenshot().getTest().getEnable().getForAll();  
   }  
   private boolean isScreenshotEnabledForFailure() {  
     return config.getReport().getScreenshot().getTest().getEnable().getOnFailure();  
   }  
   private Set<String> getScreenshotNames() {  
     return takeScreenshotAspect.getScreenshotNames();  
   }  
   private void clearScreeshotNamesForCurrentTest() {  
     takeScreenshotAspect.getScreenshotNames().clear();  
   }  
   private String getBase64EncodedScreenshot(String fileName) {  
     try {  
       byte[] bytes = FileUtils.readFileToByteArray(new File(fileName));  
       log.debug("bytes length : {}", bytes.length);  
       String base64EncodedImage = Base64.getEncoder().encodeToString(bytes);  
       log.debug("base64EncodedImage : {}", base64EncodedImage);  
       return base64EncodedImage;  
     } catch (final Exception e) {  
       String message = String.format("Issue while converting file %s to base 64 encoding %s : ", fileName, e);  
       throw new RuntimeException(message + e);  
     }  
   }  
   private ExtentTest addScreenshotToTestIfEnabled(ExtentTest test, boolean enabled) {  
     try {  
       if (enabled) {  
         String methodName = config.getReport().getScreenshot().getTest().getMethodName();  
         getScreenshotNames().forEach(  
             e -> {  
               if (e.contains(methodName)) {  
                 test.addScreenCaptureFromBase64String(getBase64EncodedScreenshot(e));  
               }  
             });  
         clearScreeshotNamesForCurrentTest();  
       }  
       return test;  
     } catch (final Exception e) {  
       String message = String.format("Exception while retrieving screenshot %s : ", e);  
       throw new RuntimeException(message + e);  
     }  
   }  
 }

Comments

Popular posts from this blog

FileSystemUtils

Report

AbstractTestNgBaseTest