001: package org.testng.remote;
002:
003: import java.util.Map;
004:
005: import org.testng.ISuite;
006: import org.testng.ISuiteListener;
007: import org.testng.ITestRunnerFactory;
008: import org.testng.TestNG;
009: import org.testng.TestNGCommandLineArgs;
010: import org.testng.TestRunner;
011: import org.testng.remote.strprotocol.GenericMessage;
012: import org.testng.remote.strprotocol.MessageHelper;
013: import org.testng.remote.strprotocol.RemoteMessageSenderTestListener;
014: import org.testng.remote.strprotocol.StringMessageSenderHelper;
015: import org.testng.remote.strprotocol.SuiteMessage;
016: import org.testng.reporters.JUnitXMLReporter;
017: import org.testng.reporters.TestHTMLReporter;
018: import org.testng.xml.XmlSuite;
019: import org.testng.xml.XmlTest;
020:
021: /**
022: * Extension of TestNG registering a remote TestListener.
023: * <p>
024: * <i>Developer note</i>: be aware that a copy of this source is distributed along with the
025: * Eclipse plugin to assure backward compatibility.
026: * </p>
027: * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
028: */
029: public class RemoteTestNG extends TestNG {
030: private static final String LOCALHOST = "127.0.0.1";
031:
032: private ITestRunnerFactory m_customTestRunnerFactory;
033: protected String m_host;
034: protected int m_port;
035:
036: public void setConnectionParameters(String host, int port) {
037: if ((null == host) || "".equals(host)) {
038: m_host = LOCALHOST;
039: } else {
040: m_host = host;
041: }
042:
043: m_port = port;
044: }
045:
046: public void configure(Map cmdLineArgs) {
047: super .configure(cmdLineArgs);
048: setConnectionParameters((String) cmdLineArgs
049: .get(TestNGCommandLineArgs.HOST_COMMAND_OPT), Integer
050: .parseInt((String) cmdLineArgs
051: .get(TestNGCommandLineArgs.PORT_COMMAND_OPT)));
052: }
053:
054: public void run() {
055: final StringMessageSenderHelper msh = new StringMessageSenderHelper(
056: m_host, m_port);
057: try {
058: if (msh.connect()) {
059: if (m_suites.size() > 0) {
060:
061: int testCount = 0;
062:
063: for (int i = 0; i < m_suites.size(); i++) {
064: testCount += ((XmlSuite) m_suites.get(i))
065: .getTests().size();
066: }
067:
068: GenericMessage gm = new GenericMessage(
069: MessageHelper.GENERIC_SUITE_COUNT);
070: gm.addProperty("suiteCount", m_suites.size())
071: .addProperty("testCount", testCount);
072: msh.sendMessage(gm);
073:
074: addListener(new RemoteSuiteListener(msh));
075: setTestRunnerFactory(new DelegatingTestRunnerFactory(
076: buildTestRunnerFactory(), msh));
077:
078: super .run();
079: } else {
080: System.err
081: .println("WARNING: No test suite found. Nothing to run");
082: }
083: } else {
084: System.err.println("Cannot connect to " + m_host
085: + " on " + m_port);
086: }
087: } catch (Throwable cause) {
088: cause.printStackTrace(System.err);
089: } finally {
090: msh.shutDown();
091: System.exit(0);
092: }
093: }
094:
095: /**
096: * Override by the plugin if you need to configure differently the <code>TestRunner</code>
097: * (usually this is needed if different listeners/reporters are needed).
098: * <b>Note</b>: you don't need to worry about the wiring listener, because it is added
099: * automatically.
100: */
101: protected ITestRunnerFactory buildTestRunnerFactory() {
102: if (null == m_customTestRunnerFactory) {
103: m_customTestRunnerFactory = new ITestRunnerFactory() {
104: public TestRunner newTestRunner(ISuite suite,
105: XmlTest xmlTest) {
106: TestRunner runner = new TestRunner(suite, xmlTest,
107: false /*skipFailedInvocationCounts */);
108: if (m_useDefaultListeners) {
109: runner.addListener(new TestHTMLReporter());
110: runner.addListener(new JUnitXMLReporter());
111: }
112:
113: return runner;
114: }
115: };
116: }
117:
118: return m_customTestRunnerFactory;
119: }
120:
121: public static void main(String[] args) {
122: Map commandLineArgs = TestNGCommandLineArgs
123: .parseCommandLine(args);
124:
125: RemoteTestNG testNG = new RemoteTestNG();
126: testNG.configure(commandLineArgs);
127:
128: testNG.run();
129: }
130:
131: /** A ISuiteListener wiring the results using the internal string-based protocol. */
132: private static class RemoteSuiteListener implements ISuiteListener {
133: private final StringMessageSenderHelper m_messageSender;
134:
135: RemoteSuiteListener(StringMessageSenderHelper smsh) {
136: m_messageSender = smsh;
137: }
138:
139: public void onFinish(ISuite suite) {
140: m_messageSender
141: .sendMessage(new SuiteMessage(suite, false /*start*/));
142: }
143:
144: public void onStart(ISuite suite) {
145: m_messageSender
146: .sendMessage(new SuiteMessage(suite, true /*start*/));
147: }
148: }
149:
150: private static class DelegatingTestRunnerFactory implements
151: ITestRunnerFactory {
152: private final ITestRunnerFactory m_delagateFactory;
153: private final StringMessageSenderHelper m_messageSender;
154:
155: DelegatingTestRunnerFactory(ITestRunnerFactory trf,
156: StringMessageSenderHelper smsh) {
157: m_delagateFactory = trf;
158: m_messageSender = smsh;
159: }
160:
161: public TestRunner newTestRunner(ISuite suite, XmlTest test) {
162: TestRunner tr = m_delagateFactory
163: .newTestRunner(suite, test);
164: tr.addListener(new RemoteMessageSenderTestListener(suite,
165: test, m_messageSender));
166:
167: return tr;
168: }
169: }
170: }
|