PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/atlassian/bamboo/plugin/dotnet/tests/nunit/NUnitXmlTestResultsParser.java

https://bitbucket.org/atlassian/bamboo-dotnet-plugin/
Java | 367 lines | 264 code | 55 blank | 48 comment | 19 complexity | 48f44626a3e8e79e0174affe4abff4e7 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. package com.atlassian.bamboo.plugin.dotnet.tests.nunit;
  2. import com.atlassian.bamboo.configuration.ConfigurationException;
  3. import com.atlassian.bamboo.configuration.DefaultElementParser;
  4. import com.atlassian.bamboo.configuration.ElementContentElementParser;
  5. import com.atlassian.bamboo.plugin.dotnet.tests.TestResultContentHandler;
  6. import com.atlassian.bamboo.plugin.dotnet.tests.TestResultsParser;
  7. import com.atlassian.bamboo.results.tests.TestResults;
  8. import com.atlassian.bamboo.resultsummary.tests.TestCaseResultErrorImpl;
  9. import com.atlassian.bamboo.resultsummary.tests.TestState;
  10. import com.google.common.annotations.VisibleForTesting;
  11. import com.google.common.collect.ImmutableList;
  12. import com.google.common.collect.Lists;
  13. import net.jcip.annotations.NotThreadSafe;
  14. import org.apache.commons.lang3.StringUtils;
  15. import org.apache.log4j.Logger;
  16. import org.jetbrains.annotations.NotNull;
  17. import org.xml.sax.Attributes;
  18. import org.xml.sax.InputSource;
  19. import org.xml.sax.XMLReader;
  20. import org.xml.sax.helpers.XMLReaderFactory;
  21. import java.io.InputStream;
  22. import java.util.List;
  23. /**
  24. * Handles parsing NUnit report files.
  25. *
  26. * @author Ross Rowe
  27. */
  28. @NotThreadSafe
  29. public class NUnitXmlTestResultsParser extends TestResultContentHandler implements TestResultsParser
  30. {
  31. /**
  32. * Handles parsing 'message' elements.
  33. *
  34. * @author Ross Rowe
  35. */
  36. public class MessageElementParser extends ElementContentElementParser
  37. {
  38. /**
  39. * Overriden to record error message details.
  40. */
  41. @Override
  42. public void endElement() throws ConfigurationException
  43. {
  44. super.endElement();
  45. if (getCurrentTestError() != null)
  46. {
  47. final StringBuilder builder = new StringBuilder();
  48. if (getCurrentTestError().getContent() != null)
  49. {
  50. builder.append(getCurrentTestError().getContent());
  51. builder.append(System.getProperty("line.separator"));
  52. }
  53. builder.append(getElementContent());
  54. setCurrentTestError(new TestCaseResultErrorImpl(builder.toString()));
  55. }
  56. }
  57. }
  58. /**
  59. * Handles parsing 'test-suite' elements.
  60. *
  61. * @author Ross Rowe
  62. */
  63. public class TestSuiteElementParser extends ElementContentElementParser
  64. {
  65. /**
  66. * Overriden to store the suite class name.
  67. */
  68. @Override
  69. public void startElement(Attributes attributes)
  70. {
  71. super.startElement(attributes);
  72. setSuiteClassName(attributes.getValue("name"));
  73. }
  74. }
  75. /**
  76. * Handles parsing 'test-case' elements.
  77. *
  78. * @author Ross Rowe
  79. */
  80. public class TestCaseElementParser extends ElementContentElementParser
  81. {
  82. /**
  83. * Overriden to store test case information.
  84. */
  85. @Override
  86. public void startElement(Attributes attributes)
  87. {
  88. super.startElement(attributes);
  89. final String testDuration = attributes.getValue("time");
  90. final String fqTestName = attributes.getValue("name");
  91. String className = attributes.getValue("classname");
  92. if (className == null && fqTestName.contains("."))
  93. {
  94. className = StringUtils.substringBeforeLast(fqTestName, ".");
  95. }
  96. final String testName = getTestName(fqTestName);
  97. final TestResults testResults = new TestResults(className != null ? className : getSuiteClassName(),
  98. testName, testDuration);
  99. testResults.setState(getTestState(attributes));
  100. setCurrentTestResult(testResults);
  101. }
  102. /**
  103. * Overriden to add currentTestResult to either <code>failedTests</code>
  104. * or <code>successfulTests</code>.
  105. */
  106. @Override
  107. public void endElement() throws ConfigurationException
  108. {
  109. super.endElement();
  110. final TestResults testResults = getCurrentTestResult();
  111. if (testResults != null)
  112. {
  113. switch (testResults.getState())
  114. {
  115. case FAILED:
  116. failedTests.add(testResults);
  117. break;
  118. case SKIPPED:
  119. inconclusiveTests.add(testResults);
  120. break;
  121. case SUCCESS:
  122. passedTests.add(testResults);
  123. break;
  124. }
  125. setCurrentTestResult(null);
  126. }
  127. }
  128. private TestState getTestState(Attributes attributes)
  129. {
  130. final boolean executed = Boolean.parseBoolean(attributes.getValue("executed"));
  131. final String result = attributes.getValue("result");
  132. final boolean success = Boolean.parseBoolean(attributes.getValue("success"));
  133. if (executed)
  134. {
  135. if (success || "Success".equalsIgnoreCase(result))
  136. {
  137. return TestState.SUCCESS;
  138. }
  139. else
  140. {
  141. return TestState.FAILED;
  142. }
  143. }
  144. else
  145. {
  146. return TestState.SKIPPED;
  147. }
  148. }
  149. }
  150. @VisibleForTesting
  151. @NotNull
  152. static String getTestName(final String fqTestName)
  153. {
  154. if (!fqTestName.contains("."))
  155. {
  156. return fqTestName;
  157. }
  158. final String fqNameWithoutParams = StringUtils.substringBefore(fqTestName, "(");
  159. return fqTestName.substring(fqNameWithoutParams.lastIndexOf(".") + 1);
  160. }
  161. public class ErrorElementParser extends ElementContentElementParser
  162. {
  163. /**
  164. * Overriden to store error details.
  165. */
  166. @Override
  167. public void endElement() throws ConfigurationException
  168. {
  169. super.endElement();
  170. TestCaseResultErrorImpl error = new TestCaseResultErrorImpl(getElementContent());
  171. if (getCurrentTestResult() != null)
  172. {
  173. getCurrentTestResult().addError(error);
  174. }
  175. else
  176. {
  177. TestResults errorTestResult = new TestResults(getSuiteClassName(), "unknownTestCase", "0.0");
  178. errorTestResult.addError(error);
  179. failedTests.add(errorTestResult);
  180. }
  181. }
  182. }
  183. /**
  184. * Handles parsing 'failure' elements'
  185. *
  186. * @author Ross Rowe
  187. */
  188. public class FailureElementParser extends ElementContentElementParser
  189. {
  190. private String message;
  191. @Override
  192. public void startElement(Attributes attributes)
  193. {
  194. super.startElement(attributes);
  195. message = attributes.getValue("message");
  196. setCurrentTestError(new TestCaseResultErrorImpl(message));
  197. }
  198. @Override
  199. public void endElement() throws ConfigurationException
  200. {
  201. super.endElement();
  202. if (getCurrentTestResult() != null)
  203. {
  204. getCurrentTestResult().addError(getCurrentTestError());
  205. getCurrentTestResult().setState(TestState.FAILED);
  206. setCurrentTestError(null);
  207. }
  208. }
  209. }
  210. /**
  211. * Constructs a NantXmlTestResultsParser instance.
  212. */
  213. public NUnitXmlTestResultsParser()
  214. {
  215. registerElementParser("categories", new DefaultElementParser());
  216. registerElementParser("category", new DefaultElementParser());
  217. registerElementParser("test-results", new DefaultElementParser());
  218. registerElementParser("environment", new DefaultElementParser());
  219. registerElementParser("culture-info", new DefaultElementParser());
  220. registerElementParser("results", new DefaultElementParser());
  221. registerElementParser("reason", new DefaultElementParser());
  222. registerElementParser("message", new MessageElementParser());
  223. registerElementParser("test-suite", new TestSuiteElementParser());
  224. registerElementParser("stack-trace", new DefaultElementParser());
  225. registerElementParser("test-case", new TestCaseElementParser());
  226. registerElementParser("error", new ErrorElementParser());
  227. registerElementParser("failure", new FailureElementParser());
  228. }
  229. public int getNumberOfErrors() {
  230. return failedTests.size();
  231. }
  232. @Override
  233. public ImmutableList<TestResults> getSuccessfulTests()
  234. {
  235. return ImmutableList.copyOf(passedTests);
  236. }
  237. @Override
  238. public ImmutableList<TestResults> getFailedTests()
  239. {
  240. return ImmutableList.copyOf(failedTests);
  241. }
  242. @Override
  243. public ImmutableList<TestResults> getInconclusiveTests()
  244. {
  245. return ImmutableList.copyOf(inconclusiveTests);
  246. }
  247. public String getSystemOut() {
  248. return systemOut;
  249. }
  250. public String getSystemErr() {
  251. return errorOut;
  252. }
  253. /**
  254. * @param inputStream
  255. */
  256. @Override
  257. public void parse(InputStream inputStream)
  258. {
  259. failedTests = Lists.newArrayList();
  260. passedTests = Lists.newArrayList();
  261. inconclusiveTests = Lists.newArrayList();
  262. try
  263. {
  264. //final XMLReader reader = SecureXmlParserFactory.newXmlReader();
  265. XMLReader reader = XMLReaderFactory.createXMLReader(DEFAULT_PARSER);
  266. reader.setContentHandler(this);
  267. reader.parse(new InputSource(inputStream));
  268. }
  269. catch (Exception e)
  270. {
  271. log.error("Failed to parse xml test results. File was null.", e);
  272. }
  273. }
  274. private static final Logger log = Logger
  275. .getLogger(NUnitXmlTestResultsParser.class);
  276. private String suiteClassName;
  277. private TestResults currentTestResult;
  278. private TestCaseResultErrorImpl currentTestError;
  279. private List<TestResults> failedTests;
  280. private List<TestResults> passedTests;
  281. private List<TestResults> inconclusiveTests;
  282. private String systemOut;
  283. private String errorOut;
  284. public TestResults getCurrentTestResult() {
  285. return currentTestResult;
  286. }
  287. public String getSuiteClassName()
  288. {
  289. return suiteClassName;
  290. }
  291. public void setCurrentTestResult(TestResults currentTestResult) {
  292. this.currentTestResult = currentTestResult;
  293. }
  294. public void setSuiteClassName(String suiteClassName) {
  295. this.suiteClassName = suiteClassName;
  296. }
  297. public String getErrorOut() {
  298. return errorOut;
  299. }
  300. public void setErrorOut(String errorOut) {
  301. this.errorOut = errorOut;
  302. }
  303. public void setSystemOut(String systemOut) {
  304. this.systemOut = systemOut;
  305. }
  306. public TestCaseResultErrorImpl getCurrentTestError() {
  307. return currentTestError;
  308. }
  309. public void setCurrentTestError(TestCaseResultErrorImpl currentTestError) {
  310. this.currentTestError = currentTestError;
  311. }
  312. }