I came up with a neat little pattern that’s helped me be more expressive in some (fairly specific) situations. Here I’ll give you a feel for it using the CountDownLatch class as an example.
CountDownLatch.await()
Using an instance of a CountDownLatch, we can wait for the latch to count down to zero, blocking the calling thread before continuing. When using a timeout, the method returns true if the count reached zero or false if the timeout expires. To make the timeout more explicit in my application code, I started with the following.
To be more concise, I wanted to wrap the logic above in some kind of helper class. Thanks to lovely static imports, a private constructor and a static factory method called await(), I was able to express the same thing with the following.
The with(...) method is the thing that actually wraps the call to the await() method on the latch. I created a Duration class in the above case to capture the timeout constant.
This can be a neat little pattern which when used sparingly can lead to little nuggets of really readable code. However, the helper class that employs the static factory can feel unnatural as the method names don’t really represent their function but rather their context within the DSL that the class defines.
Using a private constructor and verifying the internal state is essential to ensure that the DSL can’t be used incorrectly. Basically, if there are very few methods and you make sure they can only be called in a sensible order, I’d suggest its a good pattern to follow. The finished class is shown below in full.
Communication plays such a big part in what we do, we’re always striving to be more expressive in our code, conveying our intent as clearly as possible. It’s the same when pairing. We need to be expressive, communicate our intent, engage, listen and feedback. When we don’t do these things, pairing just doesn’t work. When we don’t collaborate, we’re not getting as much out of pairing as we could be. Perhaps it’s only after working in a good pair that you realise what you’re missing working in a bad pairing.
The thing I found most interesting about looking at this was having to be more explicit about the UI thread. When developing SWT applications, we’re all aware that accessing almost anything graphical in SWT from any other thread than the UI thread spells “invalid thread access”, but it was fun to be more explicit about the “UI thread”.
When I started to look at how I go about writing SWT applications, I noticed that
I often run the application from a main method somewhere which runs on the main thread.
I often discover invalid thread access problems at run time.
I often plug the problem by wrapping the offender in a Display.sync(...) or Display.async(...) call.
I often have very few long running processes that need to spawn a thread and update the UI.
It wasn’t until I started looking at being able to run the application from the context of a JUnit test that I started to think in more detail about these.
Running the application from a main method
This seems simple but being more explicit about the UI thread means that this is worth a closer look. I always used to start an SWT application from the main method, in variations of the code below.
The default constructor would do or delegate the work to setup the various shells and widgets and finally start the event loop. When using JFace’s ApplicationWindow, I’d do pretty much the same thing. Calling window.setBlockOnOpen(true) just shifts the responsibility of starting the event loop to the ApplicationWindow class. If you call window.setBlockOnOpen(false) for example, you have to manually start an event loop.
However you do it, getting into that event loop blocks the client and it’s the thread that executes this event loop that is called the UI thread. It just so happens that most SWT applications will hit that loop from the main thread as you can see from the following partial thread dump.
Name: main
State: RUNNABLE
Total blocked: 0 Total waited: 0
Stack trace:
org.eclipse.swt.internal.win32.OS.WaitMessage(Native Method)
org.eclipse.swt.widgets.Display.sleep(Unknown Source)
com.objogate...SwtCalculator.startEventLoop(SwtCalculator.java:104)
com.objogate...SwtCalculator.main(SwtCalculator.java:113)
At this point, the SWT event loop is doing its thing, waiting for UI events (mouse clicks, keyboard input etc) and dispatching them to the appropriate listeners. So, we can define what we mean by the UI thread;
The UI thread or event dispatching thread is the thread that executes the standard SWT event loop.
Running the tests and GUI in different threads
So, if the event loop was called from within say a @Before annotated method in a test, the test would block until the event loop finished, the display would be disposed and any subsequent tests against the GUI elements would quickly discover that they no longer exist.
It should be pretty clear then that in order to test GUI elements the event loop has to be started in a different thread than the tests run in. The gotcha is that the test thread will likely want to interact with this UI thread in order to push buttons and make assertions and that’s when we get into invalid thread access territory with SWT.
The way I implemented this was to use a class extending Thread to represent the UI thread and to start the event loop in its run() method. The tests can interact with the UI thread by either searching for the display with Display.findDisplay(thread) or by cooperating and ensuring that only the default display is used (retrieving it using Display.getDefault()).
A minor change to the application’s main method is required to optionally not call the event loop when calling main. For example;
The tests can then explicitly create a UI thread delegating shell setup to the SwtCalculator class before starting the event loop and allowing the test thread to continue.
@BeforepublicvoidrunTheApplication(){thread=UIThread.startNewUIThread(newUISetupClosure(){publicvoidperformAdditionalSetup(){SwtCalculator.main(DONT_BLOCK_ON_OPEN);}});ui=newSwtCalculatorDriver();}@TestpublicvoidcalculatorCanAddTwoNumbers(){// testing the calculator whilst the main thread is running and// the UI has been started in another thread (from @Before)}@AfterpublicvoidstopTheApplication(){thread.interrupt();}
The UISetupClosure allows the setup code (in this case the main method) to run inside the UI thread. This uses the strategy pattern but an alternative design could just as easily sub-class the UIThread and use the template pattern in a similar way.
The interrupt allows the event loop on the UI thread to be interrupted and stop gracefully.
The following partial thread dump shows it in action. As you can see, an explicit thread has started the event loop (the Display.sleep and WaitMessage
are the hints).
It was a good exercise exploring the UI thread and I encourage you to take a look at Window Licker (and my SWT patch). Have a play and see if you agree with the approach I took above.
Window Licker is a framework designed to help you define your own API for GUI testing. It provides a driver style API that your Swing or Ajax applications plug into before you go about writing GUI tests in a language natural to your application.
We’ve been doing some driver based GUI testing for our web apps using HtmlUnit so I was naturally interested in Window Licker with regard to rich client based testing. I’ve been trying to test my SWT based apps at the unit level as much as possible, but it’s not always straight forward separating the behaviour of GUI classes from GUI elements. How do you test that all the validation behaviour is plumbed in correctly and fires at the right time in a text box? So, Window Licker seemed like a great candidate to getting some real user style testing. Great!
The bad news is that Window Licker doesn’t yet support SWT. Boo! The good news is it gave me a great chance to have a go at implementing basic SWT support in Window Licker. Yey!
Check out the patch I wrote, or the thread where it’s discussed.
I’ve had a couple of problems running SWT applications on Mac, in particular, getting balloon tool tips to appear and incorrect invalid thread access errors. It seems that the Mac specific VM option -XstartOnFirstThread is the cure! It even addresses the bug I reported here!
It seems that by default, Java will not start on the main thread. Cocoa/Carbon starts it all and as a consequence, the SWT UI thread might get associated with it and not your main application thread. Therefore, whenever the application tries to access it (even though it looks like it owns it in your code), it may not and invalid thread access hilarity will ensue.
The flip side to this is that AWT/Swing apps and plugins might have problems.
I’ve been mocking with JMock2 for a while now and fully buy into using mocks and driving out behaviour using interfaces. However, I’m not sure I get the resistance when people want to use class imposterisers.
I’ve been doing a lot with SWT lately and generally want to unit test the UI elements. One way I’ve managed to do this is to mock parts of the GUI framework using impostorisers. Unless I want the full UI brought up, there just isn’t another way. The UI API doesn’t offer me any convenient interfaces and I can’t even create sub-classed mocks myself as SWT prevents you from sub-classing with run time checks.
I understand that by slowly teasing out behaviour during the mocking / TDD process you can clearly express the collaborations a class may have but I feel that you can still be clear about class behaviour when using an impostor. It’s just code right? I’m not sure I care that collaborations are documented as interfaces or not, my tests express the relationships and I’ve gone through the same thought process to understand clearly how the classes under test interact. So why is an impostor the bad guy?
Here, the string “bye” is never shown, it would seem that when the test method finishes it somehow messes with the threads…
Looking into things, it seems in my case that naughty Eclipse is muddying the water! The RemoteTestRunner class which Eclipse uses to run the tests ends up calling System.exit(0) after it’s run all the tests to kill the parent Java process. Even if we changed the daemon status of the thread, you’d get the same behaviour, ie, no “bye” being shown.
So, in some situations it is possible to kill a thread in a JUnit test bypassing the interrupt mechanism when running a test from Eclipse. IntelliJ actually seems to have the same behaviour but I can’t review to source to confirm.
Bit disappointing really. Things didn’t get started properly will around 12:00 on day 1. I got to attend two really interesting talks of ~30 minutes each but then got trapped in a couple of nightmarish ‘Open Spaces’ which ended up being a rather self-indulgent discussions about nothing in particular.