package org.jsystemtest.plugin; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlValue; import jsystem.extensions.report.xml.XmlReporter; import jsystem.framework.report.ExtendTestListener; import jsystem.framework.report.ExtendTestReporter; import jsystem.framework.report.TestInfo; import jsystem.framework.scenario.JTestContainer; import jsystem.framework.scenario.flow_control.AntForLoop; import jsystem.utils.FileUtils; import jsystem.utils.StringUtils; import junit.framework.AssertionFailedError; import junit.framework.Test; /** * * This reporter was suppose to mimic the behavior of surefire reporter for * better Jenkins integration. Unfortunately, it didn't work. * * @author Itai_Agmon * */ public class SurefireReporter implements ExtendTestReporter, ExtendTestListener { static Logger log = Logger.getLogger(XmlReporter.class.getName()); private static final double MILL_TO_SEC = 1000; private final String logFileName = "TEST-JSystem_maven_plugin_report.xml"; private final String logFolderName = "target/surefire-reports"; private TestSuite testSuite; private long testStart; private long testSuiteStart; public SurefireReporter() { init(); } /** * Initialize the model state. */ @Override public void init() { testSuite = new TestSuite(); testSuite.setName("JSystem Reporter"); testSuite.setTimeStamp(new Date().toString()); String hostName = "Unknown"; try { hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { log.warning("Failed to get local host name"); } testSuite.setHostName(hostName); testSuiteStart = System.currentTimeMillis(); try { createFolder(); } catch (IOException e) { log.warning("Failed in createing folder"); e.printStackTrace(); } } private void createFolder() throws IOException { File logFolder = new File(logFolderName); if (!logFolder.exists()) { if (!logFolder.mkdirs()) { throw new IOException("Failed to create log folder " + logFolderName); } } } @Override public void startTest(TestInfo testInfo) { TestCase testCase = new TestCase(); testCase.setName(testInfo.methodName); testCase.setClassName(testInfo.className); testStart = System.currentTimeMillis(); testSuite.addTestCase(testCase); } @Override public void addError(Test arg0, Throwable arg1) { testSuite.addError(); TestCase testCase = testSuite.getLastTestCase(); testCase.setError(buildFailureOrError(arg1)); testCase.setTime(getTimeDeltaInSec(testStart)); } @Override public void addFailure(Test arg0, AssertionFailedError arg1) { testSuite.addFailures(); TestCase testCase = testSuite.getLastTestCase(); testCase.setFailure(buildFailureOrError(arg1)); testCase.setTime(getTimeDeltaInSec(testStart)); } @Override public void endTest(Test arg0) { TestCase testCase = testSuite.getLastTestCase(); if (null != testCase) { testCase.setTime(getTimeDeltaInSec(testStart)); } toXml(); } /** * Parses throwable to failureOrError object. * * @param throwable * The throwable to parse * @return failureOrError */ private static FailureOrError buildFailureOrError(Throwable throwable) { FailureOrError failureOrError = new FailureOrError(); if (throwable.getMessage() != null) { failureOrError.setMessage(throwable.getMessage()); } failureOrError.setType(throwable.getClass().toString()); failureOrError.setValue(StringUtils.getStackTrace(throwable)); return failureOrError; } /** * Exports the model to XML. The file will be copies to two places, one is * the current log directory and the seconds is the JSystem root directory. */ public void toXml() { testSuite.setTime(getTimeDeltaInSec(testSuiteStart)); try { JAXBContext context = JAXBContext.newInstance(testSuite.getClass()); Marshaller marshaller = context.createMarshaller(); StringWriter sw = new StringWriter(); marshaller.marshal(testSuite, sw); FileUtils.write(logFolderName + File.separator + logFileName, sw.toString()); FileUtils.write(logFileName, sw.toString()); } catch (Exception e) { log.log(Level.SEVERE, "Failed to export report to XML", e); } } /** * Get the delta between the given time and the current time in seconds * * @param startTime * start time in milli seconds * @return time delta */ private static float getTimeDeltaInSec(final long startTime) { return (float) ((System.currentTimeMillis() - startTime) / MILL_TO_SEC); } /** The tests model **/ static class TestCase { private String name; private String className; private float time; private FailureOrError failure; private FailureOrError error; @XmlAttribute public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlAttribute(name = "classname") public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @XmlAttribute public float getTime() { return time; } public void setTime(float time) { this.time = time; } @XmlElement public FailureOrError getFailure() { return failure; } public void setFailure(FailureOrError failure) { this.failure = failure; } @XmlElement public FailureOrError getError() { return error; } public void setError(FailureOrError error) { this.error = error; } } @XmlRootElement(name = "testsuite") static class TestSuite { private int errors; private int failures; private String hostName; private String name; private float time; private String timeStamp; @XmlElement(name = "testcase") protected List<TestCase> testCaseList = new ArrayList<TestCase>(); public TestCase getLastTestCase() { if (testCaseList.size() == 0) { return null; } return testCaseList.get(testCaseList.size() - 1); } public void addFailures() { failures++; } public void addTestCase(TestCase testCase) { testCaseList.add(testCase); } @XmlAttribute public int getErrors() { return errors; } public void addError() { errors++; } @XmlAttribute public int getFailures() { return failures; } public void setFailures(int failures) { this.failures = failures; } @XmlAttribute public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } @XmlAttribute public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlAttribute public String getTimeStamp() { return timeStamp; } @XmlAttribute public float getTime() { return time; } public void setTime(float time) { this.time = time; } public void setTimeStamp(String timeStamp) { this.timeStamp = timeStamp; } @XmlAttribute public int getTests() { return testCaseList.size(); } } static class FailureOrError { private String value; private String message; private String type; @XmlAttribute public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @XmlAttribute public String getType() { return type; } public void setType(String type) { this.type = type; } @XmlValue public String getValue() { return value; } public void setValue(String value) { this.value = value; } } /** * Warnings are not supported by JUnit, so we have nothing to do. */ @Override public void addWarning(Test test) { } /** * Exports the model to XML and init the model. */ @Override public void endRun() { toXml(); init(); } /* Unused methods */ /** * This is the Junit start test, we are using the JSystem start test from * the extend test listener. */ @Override public void startTest(Test test) { } @Override public void report(String title, String message, boolean isPass, boolean bold) { } @Override public void report(String title, String message, int status, boolean bold) { } @Override public void startLoop(AntForLoop loop, int count) { } @Override public void endLoop(AntForLoop loop, int count) { } @Override public void startContainer(JTestContainer container) { } @Override public void endContainer(JTestContainer container) { } @Override public void saveFile(String fileName, byte[] content) { } @Override public void report(String title, String message, int status, boolean bold, boolean html, boolean link) { } @Override public void startSection() { } @Override public void endSection() { } @Override public void setData(String data) { } @Override public void addProperty(String key, String value) { } @Override public void setContainerProperties(int ancestorLevel, String key, String value) { } @Override public void flush() throws Exception { } @Override public void initReporterManager() throws IOException { } @Override public boolean asUI() { return false; } @Override public String getName() { return null; } }