1 package org.testng.xml; 2 3 import static org.testng.reporters.XMLReporterConfig.ATTR_DESC; 4 import static org.testng.reporters.XMLReporterConfig.ATTR_DURATION_MS; 5 import static org.testng.reporters.XMLReporterConfig.ATTR_NAME; 6 import static org.testng.reporters.XMLReporterConfig.ATTR_STATUS; 7 import static org.testng.reporters.XMLReporterConfig.TAG_CLASS; 8 import static org.testng.reporters.XMLReporterConfig.TAG_PARAMS; 9 import static org.testng.reporters.XMLReporterConfig.TAG_SUITE; 10 import static org.testng.reporters.XMLReporterConfig.TAG_TEST; 11 import static org.testng.reporters.XMLReporterConfig.TAG_TEST_METHOD; 12 13 import org.testng.ITestResult; 14 import org.testng.collections.Lists; 15 import org.testng.remote.strprotocol.GenericMessage; 16 import org.testng.remote.strprotocol.IRemoteSuiteListener; 17 import org.testng.remote.strprotocol.IRemoteTestListener; 18 import org.testng.remote.strprotocol.MessageHelper; 19 import org.testng.remote.strprotocol.SuiteMessage; 20 import org.testng.remote.strprotocol.TestMessage; 21 import org.testng.remote.strprotocol.TestResultMessage; 22 import org.testng.reporters.XMLReporterConfig; 23 import org.xml.sax.Attributes; 24 import org.xml.sax.helpers.DefaultHandler; 25 26 import java.util.List; 27 28 /** 29 * Parses testng-result.xml, create TestResultMessages and send them back to the listener 30 * as we encounter them. 31 * 32 * @author Cedric Beust <cedric (at) beust.com> 33 */ 34 public class ResultContentHandler extends DefaultHandler { 35 private int m_suiteMethodCount = 0; 36 private int m_testMethodCount = 0; 37 private SuiteMessage m_currentSuite; 38 private TestMessage m_currentTest; 39 private String m_className; 40 private int m_passed; 41 private int m_failed; 42 private int m_skipped; 43 private int m_invocationCount; 44 private int m_currentInvocationCount; 45 private TestResultMessage m_currentTestResult; 46 private IRemoteSuiteListener m_suiteListener; 47 private IRemoteTestListener m_testListener; 48 private List<String> m_params = null; 49 50 public ResultContentHandler(IRemoteSuiteListener suiteListener, 51 IRemoteTestListener testListener, boolean resolveClasses /* ignored */) { 52 m_suiteListener = suiteListener; 53 m_testListener = testListener; 54 } 55 56 @Override 57 public void startElement (String uri, String localName, 58 String qName, Attributes attributes) { 59 p("Start " + qName); 60 if (TAG_SUITE.equals(qName)) { 61 m_suiteListener.onInitialization(new GenericMessage(MessageHelper.GENERIC_SUITE_COUNT)); 62 m_suiteMethodCount = 0; 63 m_currentSuite = new SuiteMessage(attributes.getValue(ATTR_NAME), 64 true /* start */, m_suiteMethodCount); 65 m_suiteListener.onStart(m_currentSuite); 66 } else if (TAG_TEST.equals(qName)) { 67 m_passed = m_failed = m_skipped = 0; 68 m_currentTest = new TestMessage(true /* start */, m_currentSuite.getSuiteName(), 69 attributes.getValue(ATTR_NAME), m_testMethodCount, 70 m_passed, m_failed, m_skipped, 0); 71 m_testListener.onStart(m_currentTest); 72 } else if (TAG_CLASS.equals(qName)) { 73 m_className = attributes.getValue(ATTR_NAME); 74 } else if (TAG_TEST_METHOD.equals(qName)) { 75 Integer status = XMLReporterConfig.getStatus(attributes.getValue(ATTR_STATUS)); 76 m_currentTestResult = new TestResultMessage(status, m_currentSuite.getSuiteName(), 77 m_currentTest.getTestName(), m_className, attributes.getValue(ATTR_NAME), 78 attributes.getValue(ATTR_DESC), 79 attributes.getValue(ATTR_DESC), 80 new String[0], /* no parameters, filled later */ 81 0, Long.parseLong(attributes.getValue(ATTR_DURATION_MS)), 82 "" /* stack trace, filled later */, 83 m_invocationCount, m_currentInvocationCount); 84 m_suiteMethodCount++; 85 m_testMethodCount++; 86 if (status == ITestResult.SUCCESS) m_passed++; 87 else if (status == ITestResult.FAILURE) m_failed++; 88 else if (status == ITestResult.SKIP) m_skipped++; 89 } else if (TAG_PARAMS.equals(qName)) { 90 m_params = Lists.newArrayList(); 91 } 92 } 93 94 @Override 95 public void characters(char[] ch, int start, int length) { 96 if (m_params != null) { 97 String string = new String(ch, start, length); 98 String parameter = string; 99 if (parameter.trim().length() != 0) { 100 m_params.add(parameter); 101 } 102 } 103 } 104 105 @Override 106 public void endElement (String uri, String localName, String qName) { 107 if (TAG_SUITE.equals(qName)) { 108 m_suiteListener.onFinish(new SuiteMessage(null, false /* end */, m_suiteMethodCount)); 109 m_currentSuite = null; 110 } else if (TAG_TEST.equals(qName)) { 111 m_currentTest = new TestMessage(false /* start */, m_currentSuite.getSuiteName(), 112 null, m_testMethodCount, 113 m_passed, m_failed, m_skipped, 0); 114 m_testMethodCount = 0; 115 m_testListener.onFinish(m_currentTest); 116 } else if (TAG_CLASS.equals(qName)) { 117 m_className = null; 118 } else if (TAG_TEST_METHOD.equals(qName)) { 119 switch(m_currentTestResult.getResult()) { 120 case ITestResult.SUCCESS: 121 m_testListener.onTestSuccess(m_currentTestResult); 122 break; 123 case ITestResult.FAILURE: 124 m_testListener.onTestFailure(m_currentTestResult); 125 break; 126 case ITestResult.SKIP: 127 m_testListener.onTestSkipped(m_currentTestResult); 128 break; 129 default: 130 p("Ignoring test status:" + m_currentTestResult.getResult()); 131 } 132 } 133 else if (TAG_PARAMS.equals(qName)) { 134 String[] params = new String[m_params.size()]; 135 for (int i = 0; i < m_params.size(); i++) { 136 // The parameters are encoded as type:value. Since we only care about the 137 // value (and we don't receive the type anyway), use a dummy character in 138 // its place 139 params[i] = "@:" + m_params.get(i); 140 } 141 m_currentTestResult.setParameters(params); 142 m_params = null; 143 } 144 } 145 146 private static void p(String string) { 147 if (false) { 148 System.out.println("[ResultContentHandler] " + string); 149 } 150 } 151 } 152 153