DefaultTestResultListener.java
/**
* Powerunit - A JDK1.8 test framework
* Copyright (C) 2014 Mathieu Boretti.
*
* This file is part of Powerunit
*
* Powerunit is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Powerunit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Powerunit. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.powerunit.impl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import ch.powerunit.TestContext;
import ch.powerunit.TestResultListener;
import ch.powerunit.report.Error;
import ch.powerunit.report.Failure;
import ch.powerunit.report.Testcase;
import ch.powerunit.report.Testsuite;
import ch.powerunit.report.Testsuites;
/**
* @author borettim
*
*/
public class DefaultTestResultListener<T> implements TestResultListener<T> {
public DefaultTestResultListener(String targetFolder) {
this(targetFolder, null);
}
public DefaultTestResultListener(String targetFolder,
PrintStream outputConsole) {
this(targetFolder, outputConsole, null);
}
public DefaultTestResultListener(String targetFolder,
PrintStream outputConsole, PowerUnit mbean) {
this.outputConsole = outputConsole;
this.targetFolder = new File(targetFolder);
this.targetFolder.mkdirs();
this.mbean = mbean;
}
private static final JAXBContext JAXB_CONTEXT;
private final StringBuilder resumedSucess = new StringBuilder();
private final StringBuilder resumedFailure = new StringBuilder();
private final StringBuilder resumedSkipped = new StringBuilder();
/**
* @return the resumed
*/
public String getResumed() {
return "Success tests:\n" + resumedSucess.toString()
+ "\n\nSkipped tests:\n" + resumedSkipped.toString()
+ "\n\nFailed tests:\n" + resumedFailure.toString() + "\n";
}
/**
* @return the resumedSucess
*/
public String getResumedSucess() {
return resumedSucess.toString();
}
/**
* @return the resumedFailure
*/
public String getResumedFailure() {
return resumedFailure.toString();
}
/**
* @return the resumedSkipped
*/
public String getResumedSkipped() {
return resumedSkipped.toString();
}
static {
try {
JAXB_CONTEXT = JAXBContext.newInstance(Testsuites.class);
} catch (JAXBException e) {
throw new IllegalArgumentException("Unable to setup jaxb "
+ e.getMessage(), e);
}
}
private boolean error = false;
private final PrintStream outputConsole;
private final Map<String, Testsuite> result = new HashMap<>();
private final Map<String, Testsuites> results = new HashMap<>();
private final Map<String, Map<String, Testcase>> resultcase = new HashMap<>();
private final File targetFolder;
private final PowerUnit mbean;
private void printf(String format, Object... args) {
if (outputConsole != null) {
outputConsole.printf(format, args);
}
}
@Override
public void notifySetStart(String setName, String parameters) {
Testsuites tss = new Testsuites();
tss.setDisabled(0);
tss.setErrors(0);
tss.setFailures(0);
tss.setName(setName);
tss.setTests(0);
tss.setTime(0L);
results.put(setName, tss);
Testsuite ts = new Testsuite();
result.put(setName, ts);
ts.setName(setName.replace('$', '.'));
ts.setDisabled(0);
ts.setErrors(0);
ts.setFailures(0);
ts.setTests(0);
ts.setTime(0L);
resultcase.put(setName, new HashMap<>());
}
@Override
public void notifySetEnd(String setName, String parameters) {
try {
File target = new File(targetFolder, setName + ".xml");
printf("Pushing test results into %1$s%n", target.getAbsolutePath());
Object o = results.get(setName);
if (results.get(setName).getTestsuite().isEmpty()) {
o = result.get(setName);
}
if (mbean != null) {
ByteArrayOutputStream str = new ByteArrayOutputStream();
JAXB_CONTEXT.createMarshaller().marshal(o, str);
mbean.addResult(new String(str.toByteArray()));
}
JAXB_CONTEXT.createMarshaller().marshal(o, target);
} catch (JAXBException e) {
throw new IllegalArgumentException("Unable to setup jaxb "
+ e.getMessage(), e);
}
}
@Override
public void notifyStart(TestContext<T> context) {
String setName = context.getSetName()
+ (context.getParameterName() == null ? "" : context
.getParameterName());
Testsuite ts = result.get(setName);
Testcase tc = new Testcase();
tc.setName(context.getLocalTestName()
+ (context.getParameterName() == null ? "" : "["
+ context.getParameterName() + "]"));
tc.setClassname(context.getTestSuiteObject().getClass()
.getCanonicalName());
resultcase.get(setName).put(context.getFullTestName(), tc);
ts.getTestcase().add(tc);
tc.setTime(System.currentTimeMillis());
printf("Start of test %1$s%n", context.getFullTestName());
}
@Override
public void notifySuccess(TestContext<T> context) {
String setName = context.getSetName()
+ (context.getParameterName() == null ? "" : context
.getParameterName());
long end = System.currentTimeMillis();
Testsuite ts = result.get(setName);
Testcase tc = resultcase.get(setName).get(context.getFullTestName());
tc.setTime((end - tc.getTime()) / 1000);
ts.setTime(ts.getTime() + tc.getTime());
ts.setTests(ts.getTests() + 1);
printf("Success of test %1$s%n", context.getFullTestName());
resumedSucess.append("\t").append(context.getLocalTestName())
.append(" of ").append(context.getSetName()).append("\n");
}
@Override
public void notifyFailure(TestContext<T> context, Throwable cause) {
String setName = context.getSetName()
+ (context.getParameterName() == null ? "" : context
.getParameterName());
long end = System.currentTimeMillis();
Testsuite ts = result.get(setName);
Testcase tc = resultcase.get(setName).get(context.getFullTestName());
tc.setTime((end - tc.getTime()) / 1000);
ts.setTime(ts.getTime() + tc.getTime());
error = true;
ts.setFailures(ts.getFailures() + 1);
Failure f = new Failure();
tc.getFailure().add(f);
f.setType(cause.getClass().getCanonicalName());
f.setMessage(cause.getMessage());
StringBuilder stack = new StringBuilder("" + cause.getMessage())
.append('\n');
completeStack(cause, stack);
f.setContent(stack.toString());
printf("Failure of test %1$s because of %2$s%n",
context.getFullTestName(), cause.getMessage());
resumedFailure.append("\t").append(context.getLocalTestName())
.append(" of ").append(context.getSetName())
.append(" caused by ").append(cause.getMessage()).append("\n");
}
@Override
public void notifySkipped(TestContext<T> context) {
String setName = context.getSetName()
+ (context.getParameterName() == null ? "" : context
.getParameterName());
long end = System.currentTimeMillis();
Testsuite ts = result.get(setName);
Testcase tc = resultcase.get(setName).get(context.getFullTestName());
tc.setTime((end - tc.getTime()) / 1000);
ts.setTime(ts.getTime() + tc.getTime());
ts.setDisabled(ts.getDisabled() + 1);
tc.setSkipped("Skipped");
printf("Skip of test %1$s%n", context.getFullTestName());
resumedSkipped.append("\t").append(context.getLocalTestName())
.append(" of ").append(context.getSetName()).append("\n");
}
@Override
public void notifyError(TestContext<T> context, Throwable cause) {
String setName = context.getSetName()
+ (context.getParameterName() == null ? "" : context
.getParameterName());
long end = System.currentTimeMillis();
Testsuite ts = result.get(setName);
Testcase tc = resultcase.get(setName).get(context.getFullTestName());
tc.setTime((end - tc.getTime()) / 1000);
ts.setTime(ts.getTime() + tc.getTime());
error = true;
ts.setErrors(ts.getErrors() + 1);
Error e = new Error();
tc.getError().add(e);
e.setType(cause.getClass().getCanonicalName());
e.setMessage(cause.getMessage());
StringBuilder stack = new StringBuilder("" + cause.getMessage())
.append('\n');
completeStack(cause, stack);
e.setContent(stack.toString());
printf("Error of test %1$s because of %2$s%n",
context.getFullTestName(), cause.getMessage());
resumedFailure.append("\t").append(context.getLocalTestName())
.append(" of ").append(context.getSetName())
.append(" caused by ").append(cause.getMessage()).append("\n");
}
/**
* @param cause
* @param stack
*/
private void completeStack(Throwable cause, StringBuilder stack) {
for (StackTraceElement ste : cause.getStackTrace()) {
stack.append(ste.toString()).append('\n');
}
Throwable by = cause.getCause();
if (by != null) {
stack.append("caused by ").append(by.getMessage() + "\n");
completeStack(by, stack);
}
}
@Override
public void notifyParameterStart(String setName, String parameterName) {
Testsuites tss = results.get(setName);
Testsuite ts = new Testsuite();
result.put(setName + parameterName, ts);
ts.setName(setName + "[" + parameterName + "]");
ts.setDisabled(0);
ts.setErrors(0);
ts.setFailures(0);
ts.setTests(0);
ts.setTime(0L);
resultcase.put(setName + parameterName, new HashMap<>());
tss.getTestsuite().add(ts);
}
@Override
public void notifyParameterEnd(String setName, String parameterName) {
Testsuites tss = results.get(setName);
Testsuite ts = result.get(setName + parameterName);
tss.setDisabled(tss.getDisabled() + ts.getDisabled());
tss.setErrors(tss.getErrors() + ts.getErrors());
tss.setFailures(tss.getFailures() + ts.getFailures());
tss.setTests(tss.getTests() + ts.getTests());
tss.setTime(tss.getTime() + ts.getTime());
}
/**
* @return the error
*/
public boolean isError() {
return error;
}
}