Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 328342

Summary: Support for running tests in dynamic JVM languages in SWTBot
Product: [Technology] SWTBot Reporter: Geoff Bache <geoff.bache>
Component: SWTBotAssignee: Project Inbox <swtbot-inbox>
Status: NEW --- QA Contact:
Severity: enhancement    
Priority: P3 CC: mistria
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:
Attachments:
Description Flags
Eclipse application which appears to achieve what is described.
none
New suggestion for how this could work
none
Example usage testing RCP mail application in Python none

Description Geoff Bache CLA 2010-10-21 08:17:38 EDT
Build Identifier: 

(copy of posting to swtbot-dev)

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.

Reproducible: Always
Comment 1 Geoff Bache CLA 2010-10-21 08:20:00 EDT
Created attachment 181385 [details]
Eclipse application which appears to achieve what is described.

Could be integrated into the existing test runner or delivered as a separate package. Contains a fair bit of copied code from the headless Junit4 runner.
Comment 2 Geoff Bache CLA 2010-10-27 05:17:05 EDT
I did some more investigation on the SWTWorkbenchBot creation issue, and it seems that the difference is that requesting

org.eclipse.swt.widgets.Display.Displays[0]

from Java returns the Display object, whereas requesting it from Jython returns null. I don't know why this is, or really how to debug it further.

Also, I quickly ran into classloader issues using this, as Ketan had originally warned. Because I have to create the SWTWorkbenchBot in Java, it seems to end up with a different classloader than objects I create from Jython, causing clashes when one is passes to the other. I tried to find a way to set the classloader of the ScriptEngine to work around this, but failed, and nobody on the Jython mailing list could provide a suggestion either.

So basically, I am now going to drop the attempt to create a language-neutral version of this, use the older interface, and focus just on Jython. Hopefully the classloader issues can therefore be avoided.
Comment 3 Geoff Bache CLA 2011-02-20 05:41:30 EST
Created attachment 189358 [details]
New suggestion for how this could work
Comment 4 Geoff Bache CLA 2011-02-20 05:50:04 EST
Time for an update here. I now have a new attempt which I hope will be more useful. I've attached the code here now and will add an example testing the RCP mail application in Python sometime this week when I get a moment to write it out.

The key was to abandon the idea of using JSR-223 or any other interface in Java that directly starts dynamic language code. The problem with that, aside from the bugginess of JSR-223 and classloader hell that resulted, is that dynamic language testing frameworks often have an existing command-line or other interface that people expect to use, and it's useful to be able to hide the eclipse magic behind that same interface rather than present an entirely new interface involving telling Eclipse how to call the test tool rather than vice versa. 

So now the model is: start Jython or JRuby, add a runnable for your tests as a callback via this little plugin and start Eclipse via its ordinary launcher. When the callback is made, the classloader can immediately be set.

I've called this plugin "org.eclipse.swtbot.testscript" in the hope that it might be integrated into SWTBot at some point. Note this code does not actually import SWTBot code at all, even though the plugin specifies a dependency on the SWTBot finder plugin, because that dependency is assumed to exist from the Jython/JRuby code.

Any thoughts?
Comment 5 Geoff Bache CLA 2011-02-20 14:41:56 EST
Created attachment 189379 [details]
Example usage testing RCP mail application in Python

As promised, example Python code showing how this could work. Obviously some of this can be hidden in plugins for actual Python test tools rather than be present in actual test code.
Comment 6 Mickael Istria CLA 2011-02-21 04:11:58 EST
FWIW, We recently introduced our first Groovy SWTBot test case in our test suite. It is much more easier than other languages, since Groovy relies on and produces .class files and that Groovy-Eclipse is working well.

In Groovy, there are only 2 things to do: implement your test using SWTBot, and add the following to your build.properties:
sourceFileExtensions=*.java,*.groovy
compilerAdapter=org.codehaus.groovy.eclipse.ant.GroovyCompilerAdapter
compilerAdapter.useLog=true

(cf http://contraptionsforprogramming.blogspot.com/2010/08/groovy-pde-redux.html )
Comment 7 Geoff Bache CLA 2011-02-21 13:50:41 EST
Interesting. Jython uses .class files as well, but they're not quite like other class files and can't be loaded normally. Groovy was built to be a JVM dynamic language so it doesn't surprise me that things are easier there. I would imagine JRuby would be more like Jython and might benefit from something like this, but I must admit my knowledge is limited here.

I see two quite separate use cases here: just writing "normal" SWTBot tests in a dynamic language, to take advantage of the compact syntax and dynamic possibilities. There Groovy is likely to be a primary candidate, and I suspect this is Mickael's use case.

Another is to take advantage of test libraries that already exist in dynamic languages, such as Cucumber for Ruby or in my case PyUseCase for Python. This is what I'm primarily after here.