Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Platform » Creating application under UI test
Creating application under UI test [message #1603689] Fri, 06 February 2015 10:28 Go to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
Hello,

I've issued some problem to create my RCP Application under an UI Test framework. After some investiguation and try, I think there is a problem for IApplication creation in many UI testing framework. Here is some more details.

In the class org.eclipse.equinox.internal.app.EclipseAppHandle which is the one that is used to instantiate Eclipse IApplication when Eclipse run, the following codes is used to instantiate an IApplication from the Extension Registry (It's not exactly that since I've simplified the code by removing some methods, but Eclipse really does something like that) :
IExtension applicationExtension = Platform.getExtensionRegistry().getExtension(Platform.PI_RUNTIME, Platform.PT_APPLICATIONS, applicationToRun);
IConfigurationElement[] configs = applicationExtension.getConfigurationElements();
if (configs.length == 0) throw new RuntimeException(NLS.bind(Messages.application_invalidExtension, getApplicationDescriptor().getApplicationId()));
return configs[0].createExecutableExtension("run");


While many UI test launcher that I've seen :

  • PDE test : org.eclipse.pde.internal.junit.runtime.NonUIThreadTestApplication
  • SWTBot test : org.eclipse.swtbot.eclipse.core.UITestApplication and org.eclipse.swtbot.eclipse.junit.headless.UITestApplication
  • Tycho : org.eclipse.tycho.surefire.osgibooter.AbstractUITestApplication
  • And maybe more ...

use the following snippet to instantiate the IApplication under test:
IExtension extension = Platform.getExtensionRegistry().getExtension(Platform.PI_RUNTIME, Platform.PT_APPLICATIONS, applicationToRun);
Assert.isNotNull(extension, "Could not find IExtension for application: " + applicationToRun);

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;
	}
}


Which have not really the same effect... The problem is when you use a Factory (IExecutableExtension, IExecutableExtensionFactory) to create your IApplication instance.

Here is a concrete example, I have an application declaration like that :
<extension id="rcp-application" point="org.eclipse.core.runtime.applications">
	<application thread="main">
		<run class="com.test.DiFramework">
			<parameter name="class" value="org.eclipse.equinox.app.IApplication"></parameter>
			<parameter name="named" value="rcp-application-sample"></parameter>
		</run>
	</application>
</extension>


com.test.DiFramework implements IExecutableExtension, IExecutableExtensionFactory to retrieve the class instance given in parameter with the given @Named annotation (it uses a DI Framework to instantiate this class).

This example runs correctly under Eclipse but I'm unable to create this application under a test framesork since my executable extension never get the parameter and therefore cannot instantiate the class using my DI framework.

In EclipseAppHandle the IExecutableExtension#setInitializationData receives a Map as data with the class and named parameter but not in the UI Test Framework. The code for this feature is in the method Object org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(String attributeName).

Am I doing something wrong with IExecutableExtension, IExecutableExtensionFactory since I think I respect this API contract ?

If not, I think many UI Test framework has a bug in the way they create the IApplication under test and they should use the same code as EclipseAppHandler does.

I hope I've posted this at the right place since it impacts many Eclipse projects, if not, I'll move the topic or fill a bug somewhere if necessary.

Thanks in advance for response.

Jérôme
Re: Creating application under UI test [message #1611899 is a reply to message #1603689] Wed, 11 February 2015 17:37 Go to previous messageGo to next message
Eclipse UserFriend
Quote:
This example runs correctly under Eclipse but I'm unable to create this application under a test framesork since my executable extension never get the parameter and therefore cannot instantiate the class using my DI framework.

In EclipseAppHandle the IExecutableExtension#setInitializationData receives a Map as data with the class and named parameter but not in the UI Test Framework.


What is the Map in the UI test situation? Could you post your code for your DiFramework?

Those snippets should work: the createExecutableExtension() is all handled by the extension registry and there should not be any difference.

I'm not sure where you're seeing the @Named though; I think you mean the "named" parameter?

Sounds to me like you're missing one of your plugins carrying the "named" lookup data from your launch configuration.

Brian.
Re: Creating application under UI test [message #1619369 is a reply to message #1611899] Mon, 16 February 2015 14:34 Go to previous messageGo to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
Quote:
What is the Map in the UI test situation?


In the case of the UI framework, I receive null as the data parameter of the method void org.eclipse.core.runtime.IExecutableExtension.setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException

I can't post link to the JavaDoc since I've posted less than 5 messages ... so bad Confused

Quote:
Could you post your code for your DiFramework?


Here is my code (I've simplified it a bit for this post). It uses Guice to instantiate class.
public class DiFramework implements IExecutableExtension, IExecutableExtensionFactory {
	// -- parsing constants
	private final static String CLASS_NAME_PARAMETER = "class";
	private final static String NAMED_PARAMETER      = "named";
	
	/**
	 * Value from initialization
	 */
	private IConfigurationElement configuration;
	private Object data;
	private IContributor contributor;

	@Override
	public void setInitializationData(final IConfigurationElement config, final String name, final Object data) {
		// -- keep initialization value for further uses
		this.configuration = config;
		this.data          = data;
		this.contributor   = configuration.getContributor();
	}	

	@Override
	public Object create() throws CoreException {
		// -- resolve bundle
		Bundle bundle = ContributorFactoryOSGi.resolve(contributor);
		
		// -- retrieve key
		Key<?> key = retrieveKey(bundle, configuration, data);
		
		// -- create instance
		return retrieveInjector(bundle).getInstance(key);
	}
	
	/**
	 * Retrieve key from initialization value
	 * 
	 * @param bundle the bundle
	 * @param config the configuration element used to trigger this execution. 
	 *               It can be queried by the executable extension for specific configuration properties
	 * @param data adapter data in the form of a {@link String}, a {@link Hashtable}, or <code>null</code>.
	 * 
	 * @return an {@link Injector} {@link Key}
	 * 
	 * @throws CoreException if class name cannot be found or cannot be loaded
	 */
	private Key<?> retrieveKey(Bundle bundle, IConfigurationElement config, Object data) throws CoreException {
		// Retrieve class name and named
		//
		String className = null;
		String named     = null;
		
		// 1. try to query data
		//
		// -- data is a string
		if (data instanceof String) {
			className = data.toString();
		}
		// -- data is a table
		else if (data instanceof Map) {
			@SuppressWarnings("unchecked")
			Map<String, String> table = (Map<String, String>) data;
			
			// -- retrieve value, will be null if no mapping
			className = table.get(CLASS_NAME_PARAMETER);
			named     = table.get(NAMED_PARAMETER);
		}
		
		// 2. try the id of the config element
		//
		if (className == null) {
			if (config.getAttribute("id") != null) {
				className = config.getAttribute("id");
				log.debug("Found class name from config id '{}'", className);
			}
		}
		
		// -- class name not found
		if (className == null) {
			throw newCoreException("Unable to find a class name from configuration");
		}
		
		// -- load class
		final Class<?> clazz;
		try {
			clazz = bundle.loadClass(className);
		}
		catch (final InvalidRegistryObjectException e) {
			throw newCoreException(e);
		}
		catch (final ClassNotFoundException e) {
			throw newCoreException(e);
		}
		
		// -- forge key
		return named != null ? Key.get(clazz, Names.named(named)) : Key.get(clazz);
	}
}


Quote:
Those snippets should work: the createExecutableExtension() is all handled by the extension registry and there should not be any difference.


You're right, there should be no difference if each consumer call the same code, which is not the case. As I've said in my previous post, EcliseAppHandle call createExecutableExtension on the run parameter and UI Testing frameworks call it on the class parameter of the first run children.


It works correctly when my application is launched as an Eclipse Application but not when it's launched under an UI Test tools.

I'll try to reproduce this with a simple application so you can try it.
Re: Creating application under UI test [message #1619405 is a reply to message #1619369] Mon, 16 February 2015 15:01 Go to previous messageGo to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
Here is a small testing application that mimic my use case.

If you launch it as an Eclipse Application (EclipseApp.launch), you'll get the following output on the console:
Hello application 'com.example.MyApplication' with name 'My Application 1'


'com.example.MyApplication' is the class name retrieved from the class parameter and "My Application 1' is the name retrieved from the named parameter.

If you launch it as a Junit Plug-in Test (TestApp.launch), you'll get the following error on the console:
org.eclipse.core.runtime.CoreException: Unable to find a class name from configuration
	at com.example.DiFramework.newCoreException(DiFramework.java:78)
	at com.example.DiFramework.create(DiFramework.java:73)
	at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:262)
	at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:55)
	at org.eclipse.pde.internal.junit.runtime.NonUIThreadTestApplication.getApplication(NonUIThreadTestApplication.java:111)
	at org.eclipse.pde.internal.junit.runtime.NonUIThreadTestApplication.start(NonUIThreadTestApplication.java:36)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1386)


If you have sources installed in your target platform you should be able to debug the code in ConfigurationElement.createExecutableExtension method and see that UI tests does not create application the same way Eclipse does.
Re: Creating application under UI test [message #1621808 is a reply to message #1619405] Wed, 18 February 2015 04:27 Go to previous messageGo to next message
Eclipse UserFriend
The 'data' argument is a bit confusing. It's only non-null if the attribute in question has additional information other than the class name. For example, a ViewPart:

<extension point="org.eclipse.ui.views">
<view id="xxx" class="my.ViewPart:special info" />
</extension>

the "data" for "class" would be "special info".

In your case, I believe you want to use the IConfigurationElement from the setInitializationData() call (which will be the <view> element in the above) and examine its child elements.

Brian.
Re: Creating application under UI test [message #1623627 is a reply to message #1621808] Thu, 19 February 2015 08:05 Go to previous messageGo to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
I don't think I misuse the data argument since the use case is described in the interface's Java Doc (I still cannot post link to this).

If I want to use the IConfigurationElement to retrieve these arguments, I'll face the same kind of issue. Just modify my use case to display the given IConfigurationElement name and you'll see that when launched as an Eclipse Application it displays application and with the UI test launch it displays run. Therefore, I'll get 2 way to retrieve application data for something that should be similar.

I still think that there is a problem in the way the application is created under these frameworks since the behaviour is not the same as the standard Eclipse Application launcher.
Re: Creating application under UI test [message #1624069 is a reply to message #1623627] Thu, 19 February 2015 14:39 Go to previous messageGo to next message
Eclipse UserFriend
Interesting -- I've never used that second form for specifying extension-adapters, and never think of it. Sorry for being obtuse! You're completely right: it looks like a deviation that's since spread. Feel like opening bugs against the specific components?

You can work around it by having your factory check to see what attribute was used to obtain it. If "class" and your data==null then you know it's from the UITest approach and you'll need to look at the child elements.

Brian.
Re: Creating application under UI test [message #1625219 is a reply to message #1624069] Fri, 20 February 2015 08:17 Go to previous messageGo to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
Thanks for your responses.
Re: Creating application under UI test [message #1625220 is a reply to message #1625219] Fri, 20 February 2015 08:18 Go to previous messageGo to next message
Jerome Joslet is currently offline Jerome JosletFriend
Messages: 6
Registered: February 2015
Junior Member
I've opened three bugs (one for each project):
Eclipse PDE : https://bugs.eclipse.org/bugs/show_bug.cgi?id=460401
Tycho : https://bugs.eclipse.org/bugs/show_bug.cgi?id=460402
SWTBot : https://bugs.eclipse.org/bugs/show_bug.cgi?id=460403

To be complete, here is the link to the Java Doc: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore%2Fruntime%2FIExecutableExtension.html

(Now I can post link)
Re: Creating application under UI test [message #1647694 is a reply to message #1625220] Tue, 03 March 2015 15:11 Go to previous message
Harshini Garikiparthi is currently offline Harshini GarikiparthiFriend
Messages: 23
Registered: March 2015
Junior Member
Hello , I am trying to impart SWTBot on my RCP application but it throws the following error
!ENTRY org.eclipse.emf.ecp.emfstore.core 1 0 2015-03-03 00:39:53.317
!MESSAGE EMFStoreProvider received CREATE for ECPRepositoryImpl test server fusemaster

!ENTRY org.eclipse.osgi 4 0 2015-03-03 00:39:54.382
!MESSAGE Application error
!STACK 1
org.eclipse.swt.SWTError: Not implemented [multiple displays]
at org.eclipse.swt.SWT.error(SWT.java:4423)
at org.eclipse.swt.widgets.Display.checkDisplay(Display.java:767)
at org.eclipse.swt.widgets.Display.create(Display.java:908)
at org.eclipse.swt.graphics.Device.<init>(Device.java:156)
at org.eclipse.swt.widgets.Display.<init>(Display.java:507)
at org.eclipse.swt.widgets.Display.<init>(Display.java:498)
at org.eclipse.ui.internal.Workbench.createDisplay(Workbench.java:695)
at org.eclipse.ui.PlatformUI.createDisplay(PlatformUI.java:162)
at com.qualcomm.qti.qsip.rcp.Application.start(Application.java:96)
at org.eclipse.swtbot.eclipse.core.UITestApplication.start(UITestApplication.java:54)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:354)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
at org.eclipse.equinox.launcher.Main.run(Main.java:1450)
at org.eclipse.equinox.launcher.Main.main(Main.java:1426)
An error has occurred. See the log file
Please suggest the cause of this
Previous Topic:Luna menu items are crowded together
Next Topic:ILaunchListener / ILaunchesListener2 are not notified on Termination of the launch
Goto Forum:
  


Current Time: Thu Jan 23 10:20:20 GMT 2025

Powered by FUDForum. Page generated in 0.04032 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top