PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/main/java/com/atlassian/bamboo/plugin/dotnet/tests/mbunit/MBUnitXmlTestResultsParser.java

https://bitbucket.org/atlassian/bamboo-dotnet-plugin/
Java | 292 lines | 226 code | 32 blank | 34 comment | 21 complexity | f2727249aa18e318e4de285d1141af12 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. package com.atlassian.bamboo.plugin.dotnet.tests.mbunit;
  2. import com.atlassian.bamboo.plugin.dotnet.tests.TestResultContentHandler;
  3. import com.atlassian.bamboo.plugin.dotnet.tests.TestResultsParser;
  4. import com.atlassian.bamboo.results.tests.TestResults;
  5. import com.atlassian.bamboo.resultsummary.tests.TestCaseResultErrorImpl;
  6. import com.atlassian.bamboo.resultsummary.tests.TestState;
  7. import com.google.common.collect.ImmutableList;
  8. import com.google.common.collect.Lists;
  9. import net.jcip.annotations.NotThreadSafe;
  10. import org.dom4j.Document;
  11. import org.dom4j.DocumentFactory;
  12. import org.dom4j.Node;
  13. import org.dom4j.io.DocumentSource;
  14. import org.dom4j.io.SAXReader;
  15. import org.jaxen.JaxenException;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. import javax.xml.transform.Source;
  19. import javax.xml.transform.Transformer;
  20. import javax.xml.transform.TransformerFactory;
  21. import javax.xml.transform.stream.StreamResult;
  22. import javax.xml.transform.stream.StreamSource;
  23. import java.io.ByteArrayOutputStream;
  24. import java.io.InputStream;
  25. import java.util.Collections;
  26. import java.util.List;
  27. import java.util.Map;
  28. /**
  29. * Handles parsing MBUnit report files.
  30. *
  31. * @author Ross Rowe
  32. */
  33. @NotThreadSafe
  34. public class MBUnitXmlTestResultsParser extends TestResultContentHandler implements TestResultsParser
  35. {
  36. private static final Logger log = LoggerFactory.getLogger(MBUnitXmlTestResultsParser.class);
  37. private String testName;
  38. private List<TestResults> failedTests;
  39. private List<TestResults> inconclusiveTests;
  40. private List<TestResults> passedTests;
  41. private String systemOut;
  42. private String errorOut;
  43. public String getTestName() {
  44. return testName;
  45. }
  46. public void setTestName(String testName) {
  47. this.testName = testName;
  48. }
  49. /**
  50. * Indicates whether the test file contains errors.
  51. *
  52. * @return
  53. */
  54. public boolean hasErrors() {
  55. return getNumberOfErrors() > 0;
  56. }
  57. public int getNumberOfErrors() {
  58. return failedTests.size();
  59. }
  60. public int getNumberOfTests() {
  61. return failedTests.size() + passedTests.size();
  62. }
  63. @Override
  64. public ImmutableList<TestResults> getSuccessfulTests()
  65. {
  66. return ImmutableList.copyOf(passedTests);
  67. }
  68. @Override
  69. public ImmutableList<TestResults> getFailedTests()
  70. {
  71. return ImmutableList.copyOf(failedTests);
  72. }
  73. @Override
  74. public ImmutableList<TestResults> getInconclusiveTests()
  75. {
  76. return ImmutableList.copyOf(inconclusiveTests);
  77. }
  78. public String getSystemOut() {
  79. return systemOut;
  80. }
  81. public String getSystemErr() {
  82. return errorOut;
  83. }
  84. /**
  85. * @param inputStream
  86. */
  87. @Override
  88. public void parse(InputStream inputStream)
  89. {
  90. failedTests = Lists.newArrayList();
  91. inconclusiveTests = Lists.newArrayList();
  92. passedTests = Lists.newArrayList();
  93. try
  94. {
  95. final Map<String, String> uris = Collections.singletonMap("g", "http://www.gallio.org/");
  96. final DocumentFactory factory = new DocumentFactory();
  97. factory.setXPathNamespaceURIs(uris);
  98. // parse or create a document
  99. final SAXReader reader = new SAXReader();
  100. reader.setDocumentFactory(factory);
  101. final Document document = reader.read(inputStream);
  102. parse(document);
  103. }
  104. catch (Exception e)
  105. {
  106. log.error("Failed to parse xml test results. File was null.", e);
  107. }
  108. }
  109. /**
  110. * @param document
  111. * @throws JaxenException
  112. */
  113. private void parse(Document document) throws JaxenException
  114. {
  115. // handle pre MBUnit 3.0.5 format
  116. parsePreThreeZeroFiveFormat(document);
  117. // handle MBUnit 3.0.5 format
  118. parseThreeZeroFiveFormat(document);
  119. }
  120. /**
  121. * @param document
  122. */
  123. private void parseThreeZeroFiveFormat(Document document)
  124. {
  125. List testStepRuns = document.selectNodes("//g:testStepRun[g:testStep/g:metadata/g:entry/g:value/text()='Fixture']");
  126. for (Object object : testStepRuns)
  127. {
  128. Node testStepRun = (Node) object;
  129. // if the testStep is a fixture
  130. String fixtureName = testStepRun.selectSingleNode("g:testStep/g:codeReference/@type").getStringValue();
  131. List runs = testStepRun.selectNodes("g:children/g:testStepRun");
  132. for (Object runObject : runs)
  133. {
  134. Node run = (Node) runObject;
  135. final String testName = run.selectSingleNode("g:testStep/@name").getStringValue();
  136. final String testDuration = run.selectSingleNode("g:result/@duration").getStringValue();
  137. final String result = run.selectSingleNode("g:result/g:outcome/@status").getStringValue();
  138. final TestResults testResult = new TestResults(fixtureName, testName, testDuration);
  139. if ("passed".equalsIgnoreCase(result))
  140. {
  141. testResult.setState(TestState.SUCCESS);
  142. passedTests.add(testResult);
  143. }
  144. else if ("failed".equalsIgnoreCase(result))
  145. {
  146. //run a stylesheet transformation to print out the
  147. //test information
  148. InputStream inputStream = getClass()
  149. .getClassLoader()
  150. .getResourceAsStream("com/atlassian/bamboo/plugin/dotnet/tests/mbunit/Gallio-Report.txt.xsl");
  151. StreamSource source = new StreamSource(inputStream);
  152. Document newDocument = DocumentFactory.getInstance().createDocument();
  153. newDocument.add(run.detach());
  154. try
  155. {
  156. testResult.addError(new TestCaseResultErrorImpl(transform(newDocument, source)));
  157. }
  158. catch (Exception e)
  159. {
  160. log.error("Failed to transform the document", e);
  161. }
  162. testResult.setState(TestState.FAILED);
  163. failedTests.add(testResult);
  164. }
  165. else if ("skipped".equalsIgnoreCase(result))
  166. {
  167. testResult.setState(TestState.SKIPPED);
  168. inconclusiveTests.add(testResult);
  169. }
  170. else
  171. {
  172. log.info("Skipping testStepRun node with status {}", result);
  173. }
  174. }
  175. }
  176. }
  177. /**
  178. * @param document
  179. */
  180. private void parsePreThreeZeroFiveFormat(Document document)
  181. {
  182. List fixtures = document.selectNodes("//fixture");
  183. for (Object object : fixtures)
  184. {
  185. Node fixtureNode = (Node) object;
  186. String fixtureName = fixtureNode.selectSingleNode("@name").getStringValue();
  187. List runs = fixtureNode.selectNodes("//run");
  188. for (Object runObject : runs)
  189. {
  190. Node run = (Node) runObject;
  191. String fqTestName = run.selectSingleNode("@name").getStringValue();
  192. String testName = fqTestName.contains(".") && fqTestName.length() > fqTestName.lastIndexOf(".")
  193. ? fqTestName.substring(fqTestName.lastIndexOf(".") + 1)
  194. : fqTestName;
  195. String testDuration = run.selectSingleNode("@duration").getStringValue();
  196. String result = run.selectSingleNode("@result").getStringValue();
  197. if (result == null)
  198. {
  199. continue;
  200. }
  201. else
  202. {
  203. final TestResults testResult = new TestResults(fixtureName, testName, testDuration);
  204. if ("success".equalsIgnoreCase(result))
  205. {
  206. testResult.setState(TestState.SUCCESS);
  207. passedTests.add(testResult);
  208. }
  209. else if ("failure".equalsIgnoreCase(result))
  210. {
  211. // if we have an error, store it
  212. Node exceptionNode = run.selectSingleNode("exception");
  213. if (exceptionNode != null)
  214. {
  215. Node messageNode = exceptionNode.selectSingleNode("message");
  216. if (messageNode != null)
  217. {
  218. testResult.addError(new TestCaseResultErrorImpl(messageNode.getStringValue()));
  219. }
  220. }
  221. testResult.setState(TestState.FAILED);
  222. failedTests.add(testResult);
  223. }
  224. else if ("ignore".equalsIgnoreCase(result))
  225. {
  226. testResult.setState(TestState.SKIPPED);
  227. inconclusiveTests.add(testResult);
  228. }
  229. else
  230. {
  231. log.info("Skipping run node with result {}", result);
  232. }
  233. }
  234. }
  235. }
  236. }
  237. public String getErrorOut() {
  238. return errorOut;
  239. }
  240. public void setErrorOut(String errorOut) {
  241. this.errorOut = errorOut;
  242. }
  243. public void setSystemOut(String systemOut) {
  244. this.systemOut = systemOut;
  245. }
  246. public String transform(Node node, Source styleSheet) throws Exception
  247. {
  248. // perform transformation
  249. // System.setProperty("javax.xml.transform.TransformerFactory",
  250. // "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
  251. TransformerFactory factory = TransformerFactory.newInstance();
  252. Transformer transformer = factory.newTransformer(styleSheet);
  253. DocumentSource source = new DocumentSource(node);
  254. ByteArrayOutputStream out = new ByteArrayOutputStream();
  255. StreamResult result = new StreamResult(out);
  256. transformer.transform(source, result);
  257. // return resulting document
  258. return out.toString();
  259. }
  260. }