/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.report; import com.eviware.soapui.model.TestModelItem; import com.eviware.soapui.model.testsuite.ProjectRunContext; import com.eviware.soapui.model.testsuite.ProjectRunListener; import com.eviware.soapui.model.testsuite.ProjectRunner; import com.eviware.soapui.model.testsuite.TestCase; import com.eviware.soapui.model.testsuite.TestCaseRunContext; import com.eviware.soapui.model.testsuite.TestCaseRunner; import com.eviware.soapui.model.testsuite.TestProperty; import com.eviware.soapui.model.testsuite.TestRunListener; import com.eviware.soapui.model.testsuite.TestRunner.Status; import com.eviware.soapui.model.testsuite.TestStep; import com.eviware.soapui.model.testsuite.TestStepResult; import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus; import com.eviware.soapui.model.testsuite.TestSuite; import com.eviware.soapui.model.testsuite.TestSuiteRunContext; import com.eviware.soapui.model.testsuite.TestSuiteRunListener; import com.eviware.soapui.model.testsuite.TestSuiteRunner; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.xml.XmlUtils; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Collects TestRun results and creates JUnitReports * * @author ole.matzura */ public class JUnitReportCollector implements TestRunListener, TestSuiteRunListener, ProjectRunListener { HashMap<String, JUnitReport> reports; HashMap<TestCase, String> failures; HashMap<TestCase, Integer> errorCount; protected boolean includeTestPropertiesInReport = false; private int maxErrors = 0; public JUnitReportCollector() { this(0); } public JUnitReportCollector(int maxErrors) { this.maxErrors = maxErrors; reports = new HashMap<String, JUnitReport>(); errorCount = new HashMap<TestCase, Integer>(); failures = new HashMap<TestCase, String>(); } public List<String> saveReports(String path) throws Exception { File file = new File(path); if (!file.exists() || !file.isDirectory()) { file.mkdirs(); } List<String> result = new ArrayList<String>(); Iterator<String> keyset = reports.keySet().iterator(); while (keyset.hasNext()) { String name = keyset.next(); JUnitReport report = reports.get(name); String fileName = path + File.separatorChar + "TEST-" + StringUtils.createFileName(name, '_') + ".xml"; saveReport(report, fileName); result.add(fileName); } return result; } public HashMap<String, JUnitReport> getReports() { return reports; } public void saveReport(JUnitReport report, String filename) throws Exception { report.save(new File(filename)); } public String getReport() { Set<String> keys = reports.keySet(); if (keys.size() > 0) { String key = (String) keys.toArray()[0]; return reports.get(key).toString(); } return "No reports..:"; } public void afterRun(TestCaseRunner testRunner, TestCaseRunContext runContext) { TestCase testCase = testRunner.getTestCase(); JUnitReport report = reports.get(testCase.getTestSuite().getName()); HashMap<String, String> testProperties = getTestPropertiesAsHashMap(testCase); if (Status.INITIALIZED != testRunner.getStatus() && Status.RUNNING != testRunner.getStatus()) { if (Status.CANCELED == testRunner.getStatus()) { report.addTestCase(testCase.getName(), testRunner.getTimeTaken(), testProperties); } if (Status.FAILED == testRunner.getStatus()) { String msg = ""; if (failures.containsKey(testCase)) { msg = failures.get(testCase).toString(); } report.addTestCaseWithFailure(testCase.getName(), testRunner.getTimeTaken(), testRunner.getReason(), msg, testProperties); } if (Status.FINISHED == testRunner.getStatus()) { report.addTestCase(testCase.getName(), testRunner.getTimeTaken(), testProperties); } } } protected HashMap<String, String> getTestPropertiesAsHashMap(TestModelItem testCase) { HashMap<String, String> testProperties = new HashMap<>(); for (Map.Entry<String, TestProperty> stringTestPropertyEntry : testCase.getProperties().entrySet()) { testProperties.put(stringTestPropertyEntry.getKey(), stringTestPropertyEntry.getValue().getValue()); } return testProperties; } public void afterStep(TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result) { TestStep currentStep = result.getTestStep(); TestCase testCase = currentStep.getTestCase(); if (result.getStatus() == TestStepStatus.FAILED) { if (maxErrors > 0) { Integer errors = errorCount.get(testCase); if (errors == null) { errors = 0; } if (errors >= maxErrors) { return; } errorCount.put(testCase, errors + 1); } StringBuffer buf = new StringBuffer(); if (failures.containsKey(testCase)) { buf.append(failures.get(testCase)); } buf.append("<h3><b>").append(XmlUtils.entitize(result.getTestStep().getName())) .append(" Failed</b></h3><pre>"); for (String message : result.getMessages()) { if (message.toLowerCase().startsWith("url:")) { String url = XmlUtils.entitize(message.substring(4).trim()); buf.append("URL: <a target=\"new\" href=\"").append(url).append("\">").append(url) .append("</a>"); } else { buf.append(message); } buf.append("\r\n"); } // use string value since constant is defined in pro.. duh.. if (testRunner.getTestCase().getSettings().getBoolean("Complete Error Logs")) { StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); result.writeTo(writer); buf.append(XmlUtils.entitize(stringWriter.toString())); } buf.append("</pre><hr/>"); failures.put(testCase, buf.toString()); } } public void beforeRun(TestCaseRunner testRunner, TestCaseRunContext runContext) { TestCase testCase = testRunner.getTestCase(); TestSuite testSuite = testCase.getTestSuite(); if (!reports.containsKey(testSuite.getName())) { JUnitReport report = new JUnitReport(); report.setIncludeTestProperties(this.includeTestPropertiesInReport); report.setTestSuiteName(testSuite.getProject().getName() + "." + testSuite.getName()); reports.put(testSuite.getName(), report); } } public void beforeStep(TestCaseRunner testRunner, TestCaseRunContext runContext) { } public void beforeStep(TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep) { } public void reset() { reports.clear(); failures.clear(); errorCount.clear(); } public void afterRun(TestSuiteRunner testRunner, TestSuiteRunContext runContext) { } public void afterTestCase(TestSuiteRunner testRunner, TestSuiteRunContext runContext, TestCaseRunner testCaseRunner) { testCaseRunner.getTestCase().removeTestRunListener(this); } public void beforeRun(TestSuiteRunner testRunner, TestSuiteRunContext runContext) { } public void beforeTestCase(TestSuiteRunner testRunner, TestSuiteRunContext runContext, TestCase testCase) { testCase.addTestRunListener(this); } public void afterRun(ProjectRunner testScenarioRunner, ProjectRunContext runContext) { } public void afterTestSuite(ProjectRunner testScenarioRunner, ProjectRunContext runContext, TestSuiteRunner testRunner) { testRunner.getTestSuite().removeTestSuiteRunListener(this); } public void beforeRun(ProjectRunner testScenarioRunner, ProjectRunContext runContext) { } public void beforeTestSuite(ProjectRunner testScenarioRunner, ProjectRunContext runContext, TestSuite testSuite) { testSuite.addTestSuiteRunListener(this); } /** * Use this factory method to allow usage of an external reportCollecto; it * checks for a soapui.junit.reportCollector system property that should * specify a class derived from this JUnitReportCollector which will be used * instead * * @param maxErrors */ public static JUnitReportCollector createNew(int maxErrors) { String className = System.getProperty("soapui.junit.reportCollector", null); if (StringUtils.hasContent(className)) { try { return (JUnitReportCollector) Class.forName(className).getConstructor(Integer.class) .newInstance(maxErrors); } catch (Exception e) { System.err.println("Failed to create JUnitReportCollector class [" + className + "]; " + e.toString()); } } return new JUnitReportCollector(maxErrors); } public void setIncludeTestPropertiesInReport(boolean includeTestPropertiesInReport) { this.includeTestPropertiesInReport = includeTestPropertiesInReport; } }