Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[swtbot-dev] SWTbot tests in dynamic languages (Jython)

Hi all,

After suggestions from Ketan I've created my own Eclipse application
that I believe should be able to run SWTBot tests in any dynamic
language just by pointing out a source file. I have only tested it on
a minimal example using Jython but in principle it ought to work. I
attach the source code for this.

I can then basically write a Python test for the rcpmail example:
first I run this under Jython:

allArgs = [ "-application", "org.eclipse.swtbot.testscript.application",
            "-testApplication", "org.rcpmail", "-product",
"org.rcpmail.product",
            "-testScript", "/users/geoff/tmp/rcptest.py" ]
import org.eclipse.equinox.launcher as launcher
launcher.Main.main(allArgs)

and then write this in rcptest.py : "bot" is a global variable set up
by the attached Java code:

bot.menu("File").menu("Open Another Message View").click()
bot.viewByTitle("Message")

then I can achieve the same things as in the inital example using Python.

The surprise here was that it did not work to create the
SWTWorkbenchBot in Python. If I tried it just threw
IllegalStateException the whole time (and this wasn't a timing issue,
I could wait forever and still got this). It is iterating through all
existing threads and I suspect there is some clash between Java and
Jython threads. I worked around this by creating it in Java and adding
it to the global namespace of the script.

Regards,
Geoff Bache
package org.eclipse.swtbot.testscript;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.testing.ITestHarness;
import org.eclipse.ui.testing.TestableObject;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
 * Copied from the headless test runner: the point here is to support running dynamic language scripts
 * in e.g. Python, Groovy or Ruby, primarily for testing
 */
public class Application implements IApplication, ITestHarness {

	private static final String	DEFAULT_APP_3_0	= "org.eclipse.ui.ide.workbench";	//$NON-NLS-1$

	private TestableObject		fTestableObject;
	private IApplication		fApplication;

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
	 */
	public Object start(IApplicationContext context) throws Exception {
		String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
		Object app = getApplication(args);

		Assert.isNotNull(app);

		fTestableObject = PlatformUI.getTestableObject();
		fTestableObject.setTestHarness(this);
		if (app instanceof IApplication) {
			fApplication = (IApplication) app;
			return fApplication.start(context);
		}
		throw new IllegalArgumentException("Could not execute application " + getApplicationToRun(args));
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#stop()
	 */
	public void stop() {
		if (fApplication != null)
			fApplication.stop();
	}

	/*
	 * return the application to run, or null if not even the default application is found.
	 */
	private Object getApplication(String[] args) throws CoreException {
		// Find the name of the application as specified by the PDE JUnit launcher.
		// If no application is specified, the 3.0 default workbench application
		// is returned.
		IExtension extension = Platform.getExtensionRegistry().getExtension(Platform.PI_RUNTIME, Platform.PT_APPLICATIONS,
				getApplicationToRun(args));

		Assert.isNotNull(extension);

		// If the extension does not have the correct grammar, return null.
		// Otherwise, return the application object.
		IConfigurationElement[] elements = extension.getConfigurationElements();
		if (elements.length > 0) {
			IConfigurationElement[] runs = elements[0].getChildren("run"); //$NON-NLS-1$
			if (runs.length > 0) {
				Object runnable = runs[0].createExecutableExtension("class"); //$NON-NLS-1$
				if (runnable instanceof IApplication)
					return runnable;
			}
		}
		return null;
	}

	/*
	 * The -testApplication argument specifies the application to be run. If the PDE JUnit launcher did not set this
	 * argument, then return the name of the default application. In 3.0, the default is the
	 * "org.eclipse.ui.ide.worbench" application.
	 */
	private String getApplicationToRun(String[] args) {
		IProduct product = Platform.getProduct();
		if (product != null)
			return product.getApplication();
		return getArgument(args, "-testApplication", DEFAULT_APP_3_0);
	}

	private String getArgument(String[] args, String argName, String defaultValue) {
		for (int i = 0; i < args.length; i++)
			if (args[i].equals(argName) && (i < args.length - 1)) //$NON-NLS-1$
				return args[i + 1];
		return defaultValue;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.testing.ITestHarness#runTests()
	 */
	public void runTests() {
		fTestableObject.testingStarting();
		try {
			String testScript = getArgument(Platform.getCommandLineArgs(), "-testScript", null);
			if (testScript == null)
				throw new IllegalArgumentException("Test script file not specified"); //$NON-NLS-1$
			runScript(testScript);
		} catch (Exception e) {
			e.printStackTrace();
		}
		fTestableObject.testingFinished();
	}

	private void runScript(String testScript) throws ScriptException, IOException {
		String extension = getExtension(testScript);
		SWTWorkbenchBot bot = new SWTWorkbenchBot();
        ScriptEngine engine = new ScriptEngineManager().getEngineByExtension(extension);
        engine.put("bot", bot);
        BufferedReader reader = new BufferedReader(new FileReader(testScript));
        engine.eval(reader);
	}

	private String getExtension(String testScript) {
		String[] parts = testScript.split("\\.");
		return parts[parts.length - 1];
	}
}

Back to the top