A Simple way to extend SWTBot

Home  >>  Common  >>  A Simple way to extend SWTBot

A Simple way to extend SWTBot

On October 26, 2012, Posted by , In Common,Eclipse, With No Comments

SWTBot is an Eclipse project that enables you to write functional tests for SWT and Workbench based applications in Java.
It has API to remote control the application under test and matcher to find widgets and examine their state. For each widget there is a corresponding bot class with methods to control the widget. To enter some text into a text widget for example, your code would look like this:

Text text = new Text( parent, SWT.BORDER );
...
SWTBotText textBot = new SWTBotText( text );
textBot.typeText( "Hello World" );

Though SWTBot covers most of the API that SWT has to offer, there are some gaps. Say you want to maximize a Shell and afterwards ensure that certain widgets within that Shell behave as expected. And just the SWTBotShell.maximize() method is one of these missing ones. Or your application uses a custom widget that no one has written a bot for yet.

So help yourself and write your own bot.

To understand how a bot works, let us first look into one aspect of SWTBot, the threading model. Running a test with SWTBot usually involves two threads. The widgets under test run on the UI thread. The bot runs on an extra thread and communicates with the UI thread in that it posts events to the UI thread or uses Display.syncE­xec() to run code on the UI thread.

This is usually necessary because the UI code at some point calls Display.sleep() – e.g. from the main event loop or to create a blocking dialog. sleep() suspends the UI thread and waits until an event is received. If the test code (which generates the events sleep() is waiting for) was running on the same thread, it would be blocked infinitely.
However, if you can ensure that the code under test doesn’t call sleep(), then of course you can safely run your test code on the UI thread.

Once you have a clear understanding of that, writing your own bot is easy 1.

public class SWTBotShellExtension extends AbstractSWTBot {

  public SWTBotShellExtension( Shell shell ) 
    throws WidgetNotFoundException
  {
    super( shell );
  }

  public void maximize() {
    syncE xec( new VoidResult() {
      public void run() {
        widget.setMaximized( true );
      }
    } );
  }
}

The superclass AbstractSWTBot brings syncE­xec() methods that run the a given piece of code on the UI thread. There are several overloaded variants that accept runnables with different return types. For now we will use its simplest form, syncE­xec(VoidResult) to maximize the shell without returning anything.

The test code can now execute new SWTBotShellExtension( shell ).maximize() and voila, the given shell will be maximized. If you prefer you can inherit from SWTBotShell to have access to the other bot methods from within the same instance.

As inter-thread communication is involved, you may want the bot to be more fail safe. Take a look a the snippet below:

  public void maximize() {
    new SWTBot().waitUntil( new DefaultCondition() {

      public boolean test() {
        return syncE xec( new BoolResult() {
          public Boolean run() {
            widget.setMaximized( true );
            return Boolean.valueOf( widget.getMaximized() );
          }
        } );
      }

      public String getFailureMessage() {
        return "Timed out waiting for shell to get maximized";
      }

    } );
  }

waitUntil() executes the test method in intervals until it either returns true or a timeout is reached. If the operation times out, an exception is thrown with a message from getFailureMessage()

This is where another of the syncE­xec() method becomes useful: syncE­xec(BoolResult). Now, the code maximizes the shell, and reports back whether the shell was actually maximized. Due to the waitUntil(), this is executed as long as takes to succeed – or until the time limit is reached.

The AbstractSWTBot also provides a notify() method that can be used send events. In our case, the maximize() method issues a resize event as if the action was initiated by a user. Other actions might not always behave so in which case you can use notify() to simulate the event.

There is certainly much more to it. But creating a simple custom bot is pretty easy, isn’t it? If you have any questions or comments, please post them here.


  1. Excuse the artificial space in syncE xec, a security facility on our hosted server wouldn’t let the text pass without.

Rüdiger Herrmann

Rüdiger started writing software more than 20 years ago. From the very beginning he focused on a pragmatic approach to writing and delivering software.

His interests include promoting test driven development and agile methods to deliver clean code that works.

(EMail: rherrmann@codeaffine.com)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>