package unittesting;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlException;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import com.mendix.systemwideinterfaces.core.IContext;
import unittesting.proxies.TestSuite;
import unittesting.proxies.UnitTest;
import unittesting.proxies.UnitTestResult;
public class UnitTestRunListener extends RunListener {
private IContext context;
private TestSuite testSuite;
public UnitTestRunListener(IContext context, TestSuite testSuite) {
this.context = context;
this.testSuite = testSuite;
}
@Override
public void testRunStarted(Description description) throws java.lang.Exception {
TestManager.LOG.info("Starting test run");
}
@Override
public void testRunFinished(Result result) throws java.lang.Exception {
TestManager.LOG.info("Test run finished");
}
@Override
public void testStarted(Description description) throws java.lang.Exception {
String message = "Starting JUnit test " + description.getClassName() + "." + description.getMethodName();
TestManager.LOG.info(message);
TestManager.instance().reportStep(message);
UnitTest t = getUnitTest(description);
t.setResult(UnitTestResult._1_Running);
t.setResultMessage("");
t.setLastRun(new Date());
t.commit();
}
private UnitTest getUnitTest(Description description) {
return TestManager.instance().getUnitTest(context, testSuite, description, false);
}
@Override
public void testFinished(Description description) throws Exception {
TestManager.LOG.info("Finished test " + description.getClassName() + "." + description.getMethodName());
UnitTest t = getUnitTest(description);
if (t.getResult() == UnitTestResult._1_Running) {
t.setResult(UnitTestResult._3_Success);
long delta = getUnitTestInnerTime(description, t);
t.setResultMessage("JUnit test completed successfully");
t.setReadableTime((delta > 10000 ? Math.round(delta / 1000) + " seconds" : delta + " milliseconds"));
}
t.setLastStep(TestManager.instance().getLastReportedStep());
t.commit();
}
@Override
public void testFailure(Failure failure) throws java.lang.Exception {
boolean isCloudSecurityError =
failure.getException() != null &&
failure.getException() instanceof AccessControlException &&
((AccessControlException) failure.getException()).getPermission().getName().equals("accessDeclaredMembers");
UnitTest t = getUnitTest(failure.getDescription());
/**
* Test itself failed
*/
TestManager.LOG.error("Failed test (at step '" + TestManager.instance().getLastReportedStep() + "') " + failure.getDescription().getClassName() + "." + failure.getDescription().getMethodName() + " : " + failure.getMessage(), failure.getException());
testSuite.setTestFailedCount(testSuite.getTestFailedCount() + 1);
testSuite.commit();
t.setResult(UnitTestResult._2_Failed);
t.setResultMessage(String.format("%s %s: %s\n\n:%s",
isCloudSecurityError ? "CLOUD SECURITY EXCEPTION \n\n" + TestManager.CLOUD_SECURITY_ERROR : "FAILED",
findProperExceptionLine(failure.getTrace()),
failure.getMessage(),
failure.getTrace()
));
t.setLastStep(TestManager.instance().getLastReportedStep());
t.setLastRun(new Date());
t.commit();
}
private long getUnitTestInnerTime(Description description, UnitTest t)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException
{
long delta = System.currentTimeMillis() - t.getLastRun().getTime();
if (AbstractUnitTest.class.isAssignableFrom(description.getTestClass()))
delta = (Long) description.getTestClass().getMethod("getTestRunTime").invoke(null);
return delta;
}
private String findProperExceptionLine(String trace)
{
String[] lines = StringUtils.split(trace,"\n");
if (lines.length > 2)
for(int i = 1; i < lines.length; i++) {
String line = lines[i].trim();
if (!line.startsWith("at org.junit") && line.contains("("))
return " at " + line.substring(line.indexOf('(') + 1, line.indexOf(')')).replace(":"," line ");
}
return "";
}
}