package com.redhat.qe.auto.testng; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.SkipException; import org.testng.internal.IResultListener; import com.redhat.qe.auto.tcms.ImplementsNitrateTest; /** * This class listens for TestNG events, and logs them using the * standard java logging facility. * * In order to use this listener, the class name must be provided to testNG * using the -listener option (or specified as the attribute 'listener' * in an ant call to testng). * @author jweiss * */ public class TestNGListener implements IResultListener, ISuiteListener { protected static Logger log = Logger.getLogger(TestNGListener.class.getName()); //Override TestNG's Test Listener methods for logging purposes @Override public void onFinish(ITestContext context){ log.log(Level.INFO, "Finished TestNG Script: " + context.getName(), LogMessageUtil.Style.Banner); } @Override public void onStart(ITestContext context) { log.log(Level.INFO, "Starting TestNG Script: " + context.getName(), LogMessageUtil.Style.Banner); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { log.log(Level.WARNING, "Test Failed (but within success percentage): "+ result.getName(), result.getThrowable()); } @Override public void onTestFailure(ITestResult result) { Reporter.setCurrentTestResult(result); Throwable err = result.getThrowable(); LogRecord logRecord = new LogRecord(Level.SEVERE, "Test Failed: "+ result.getName()); logRecord.setThrown(err); if (err != null && err instanceof AssertionError) logRecord.setParameters(new Object[] {LogMessageUtil.Style.AssertFailed}); log.log(logRecord); } @Override public void onTestSkipped(ITestResult result) { Reporter.setCurrentTestResult(result); if (result.getThrowable() != null){ LogRecord r= new LogRecord(Level.INFO, "Skipping test " + result.getName() + ": " + result.getThrowable().getMessage()); r.setParameters(new Object[]{LogMessageUtil.Style.Banner}); log.log(r); } else { log.log(Level.INFO, "Skipping Test " + result.getName() + ": Unsatisfied dependency", LogMessageUtil.Style.Banner); } } @Override public void onTestStart(ITestResult result) { Reporter.setCurrentTestResult(result); LogRecord r= new LogRecord(Level.INFO, String.format("Starting Test: %s%s", result.getName(), getParameters(result))); r.setParameters(new Object[]{LogMessageUtil.Style.Banner, LogMessageUtil.Style.StartTest}); log.log(r); // embed an entry in the log to the corresponding Nitrate test case Method method = result.getMethod().getMethod(); Annotation[] annotations = method.getAnnotations(); for(Annotation annotation : annotations){ if(annotation instanceof ImplementsNitrateTest){ ImplementsNitrateTest nitrateTest = (ImplementsNitrateTest) annotation; // Examples: // https://tcms.engineering.redhat.com/case/7889/history/?from_plan=792&case_text_version=6" // https://tcms.engineering.redhat.com/case/7889/?from_plan=792 // https://tcms.engineering.redhat.com/case/7889 // https://tcms.engineering.redhat.com/case/7889/history/?from_plan=&case_text_version=6 int caseId = nitrateTest.caseId(); int version = nitrateTest.version(); int fromPlan = nitrateTest.fromPlan(); String baseUrl = nitrateTest.baseUrl(); String logMsg = String.format("This automated test implements Nitrate test %s/case/%d/history/?from_plan=%s&case_text_version=%s", baseUrl, caseId, fromPlan==0?"":fromPlan, version==0?"":version); if (version==0) { logMsg = logMsg.replace("&case_text_version=", ""); logMsg = logMsg.replace("history/", ""); if (fromPlan==0) { logMsg = logMsg.replace("?from_plan=", ""); } } log.info(logMsg); } } } @Override public void onTestSuccess(ITestResult result) { Reporter.setCurrentTestResult(result); Throwable throwable = result.getThrowable(); if (throwable != null){ log.log(Level.INFO, "Expected exception of " + throwable.getClass().getName() + " '" + throwable.getMessage() + "' was in fact thrown." , LogMessageUtil.Style.Asserted); } log.log(Level.INFO, String.format("Test Passed: %s%s", result.getName(), getParameters(result)), LogMessageUtil.Style.Banner); } @Override public void onConfigurationFailure(ITestResult result) { Reporter.setCurrentTestResult(result); log.log(Level.SEVERE, "Configuration Failed: " + result.getName(), result.getThrowable()); } @Override public void onConfigurationSkip(ITestResult result) { Reporter.setCurrentTestResult(result); if (result.getThrowable() != null){ LogRecord r= new LogRecord(Level.INFO, "Skipping configuration " + result.getName() + ": " + result.getThrowable().getMessage()); r.setParameters(new Object[]{LogMessageUtil.Style.Banner}); log.log(r); } else { log.log(Level.INFO, "Skipping configuration " + result.getName() + ": Unsatisfied dependency", LogMessageUtil.Style.Banner); } } @Override public void onConfigurationSuccess(ITestResult result) { Reporter.setCurrentTestResult(result); log.log(Level.FINE, "Configuration completed: " + result.getTestClass().getName() + "." + result.getName() , LogMessageUtil.Style.Banner); } @Override public void onFinish(ISuite suite) { log.log(Level.INFO, "Finishing TestNG Suite:" + suite.getName(), LogMessageUtil.Style.Banner); } @Override public void onStart(ISuite suite) { log.log(Level.INFO, "Starting TestNG Suite:" +suite.getName(), LogMessageUtil.Style.Banner); } public String getParameters(ITestResult result) { String params = ""; Object[] parameters = result.getParameters(); if (parameters != null && parameters.length > 0) params = "(" + Arrays.deepToString(parameters) + ")"; return params; } }