Testing plain SWT with SWTBot by Dirk Fauth

SWTBot is a testing tool for testing Eclipse and SWT based applications. If you search for SWTBot you will find some tutorials and a documentation showing how to test an Eclipse application or product. This is very easy. Following the documentation or the tutorials, the most complex thing about SWTBot seems to be finding the widgets to interact with.

But what if you like to test a plain SWT application, or your custom SWT control with SWTBot without the overhead of creating an Eclipse application? I searched the web for the last few days about this. Also asked in the SWTBot forum. But I wasn’t satisfied by the answers I got or found. So I searched further and did some investigation on this. The following are my conclusions on that, any comments are welcome.

First I want to thank Mickael Istria who was very responsive and helpful about my questions in the forum (http://www.eclipse.org/forums/index.php/t/448874/). The only problem I had with his answers in first place was, I didn’t understood what he was telling me because I was missing an important part. I already understood that SWTBot is a simple API build on top of SWT. Well, at least I thought I understood until now. So here is my conclusion:

“SWTBot is a simple API on top of SWT”

This sentence is more important and contains more information than it looks like. You need to think of SWTBot as a robot that you can command to do stuff in your UI. It is used to simulate user interaction in first place, nothing more, nothing less. You use it for automated GUI testing, but of course you could also use it for programmatically doing stuff in your GUI (which I would not suppose to do, but it is possible).

“Starting an Eclipse based application automatically is convenience”

It is really a great feature of SWTBot that it can start an Eclipse based application, connecting to it automatically in the back for running your test cases against it. Especially because this also works headless. But this kind of “magic” is only available for Eclipse based applications. So stop searching for that regarding plain SWT. For this you have to do it yourself!

To explain what I mean with the statements above, let’s have a short look on how to test an Eclipse based application using SWTBot. After you managed your dependencies for SWTBot in your test plugin, you can implement a simple class like described in several tutorials. You will find some links at the end of this blog that will lead you to some more documentation on that.

public class UITestClass {
    private static SWTWorkbenchBot bot = new SWTWorkbenchBot();

    @Test
    public void doSomeTest() {
        bot.button(“Action”).click();
        //assert some states after the click
    }
}

To run this test you need to tell SWTBot for which application the tests should be executed. If you have installed the SWTBot IDE Integration, you can do this within your Eclipse IDE by running the test class as “SWTBot Test”. You just need to configure the product or application to run in your run configuration. In your Maven Tycho build, you need to set these informations to the configuration of the tycho-surefire-plugin. With this convenience you don’t have to care about starting/stoping the application to test within your test classes. SWTBot will do that for you. This is done by re-using the PDE mechanism for running a test as a Plugin Test. So it is build on top of existing Eclipse testing features rather than some custom implementation.

Knowing about this convenience I searched something similar for testing a plain SWT application. But of course there is no such convenience for plain SWT. If you want to test your SWT application, you need to start and stop the application yourself. I created the following example to test a custom SWT control on a simple Shell.

public class SWTTestClass {

    @Test
    public void doSomeTest() {
        final Display display = Display.getDefault();
        final Shell shell = new Shell(display, SWT.SHELL_TRIM);

        Realm.runWithDefault(
            SWTObservables.getRealm(display), new Runnable() {

            public void run() {
                createMyControl(shell);

                shell.open();

                bot = new SWTBot();
                bot.button(“Action”).click();   
                //assert some states after the click
            }
        });

        shell.dispose();
        display.dispose();
    }
}

Looking at the code above, it doesn’t look like a typical JUnit test class anymore. Compared to the test cases you are able to write for an Eclipse based application, this looks ugly. To get back the feeling of writing JUnit tests you know and that probably look similar to the JUnit tests for Eclipse based applications using SWTBot, you should have a look at this project on GitHub:

https://github.com/bluezio/swtbot-pure-maven-example

This project shows how to use SWTBot to test plain SWT applications with pure Maven. For me the most interesting in this project is the IsolatedShellTest class. It provides the initialization and closing of the SWT application as a bracket to your real test cases. You simply need to extend the IsolatedShellTest and implement createShell() to tell the bracket on which Shell to operate.

As I don’t want to adorn myself with borrowed plumes, I’ll leave you looking at that project yourself, just telling you that it uses java.util.concurrent.CyclicBarrier to achieve the implementation of such a bracket. With Java 8 and its Lambda expressions or other programming languages on the JVM that support closures like Groovy for example, you would also have other solution for this. But that’s worth another blog post.

There is of course another much simpler approach for testing a custom SWT control with SWTBot. As I like such research activity, because you always learn interesting stuff, it is ok for me, but of course I could have figured out about this earlier. You can benefit of all that cool SWTBot stuff for testing your custom SWT control if you simply create a new Eclipse based application in your test plugin, that only consists of a window and a part containing your control. With Eclipse 4 such an application is created in a few minutes (or less using the wizards). Well SWTBot is currently not completely ready for testing a whole Eclipse 4 application. But they are working heavily on that, and for my case it worked fine.

http://wiki.eclipse.org/SWTBot
http://www.vogella.com/articles/SWTBot/article.html

About Dirk Fauth

Dirk Fauth is a Software Architect for Rich Client Systems working for the Robert Bosch GmbH in Stuttgart and a lecturer in Java basics for the Baden-Wuerttemberg Cooperative State University (DHBW). He is active in developing, teaching and talking about OSGi, Eclipse RCP applications and Eclipse related technologies. He is project lead of the Nebula NatTable project, Eclipse Platform committer and also a committer and contributor to several other Eclipse projects. (Twitter: @fipro78)
This entry was posted in Dirk Fauth, Eclipse. Bookmark the permalink.

2 Responses to Testing plain SWT with SWTBot by Dirk Fauth

  1. Jmini says:

    Instead of packing all your before / after JUnit logic into an abstract test class (IsolatedShellTest), I think that a nicer way is to use the @Rule annotation. For instance with ExternalResource you can execute code before and after a test method.

    https://github.com/KentBeck/junit/wiki/Rules

    What do you think from these improvements to JUnit ?

  2. Dirk Fauth says:

    I have to admit that I didn’t knew about JUnit Rules until now. I looked into them and tried to implement the IsolatedShellTest as a Rule. Checking it in short, it seems that you just moving the code from the abstract class to extend for creating your tests from, to an abstract Rule you need to extend for every test you like to implement. In both cases you have to provide the information about creating/opening the Shell and you need to ensure to handle the threading so SWTBot is able to interact.

    Nevertheless, Rules (or Interceptors as they were named before) are looking very nice. 🙂

Comments are closed.