ULC Testing with Jemmy

Purpose

Automated testing with JUnit has become an integral part of software development. Already well established for module testing this technique has also been extended to user interface testing. A number of libraries are available for Swing which support programmatic access to the user interface in order to write test cases. Examples are Jemmy, Jelly, or JFCUnit. This article explains how to use JUnit and Jemmy for automated user interface testing with ULC.

How to use

In addition to the Jemmy and JUnit libraries you need to include the classes TestEnvironment and JemmyHelper with your project. Both classes come with the example code. For starting your ULC application a new AbstractApplication has to be implemented. This class initializes the TestEnvironment in its start method and implements a handleMessage method to execute testing code in the context of a server session.

Test cases are simple and straightforward. The example code shows how to implement test cases for a simple GUI. The setup() method creates the part of the user interface to be tested and the tearDown() method releases the user interface. In addition, the setup()method creates an instance of JemmyHelper and starts the application to be tested by calling the init() method of AutomatedGUITesting. AutomatedGUITesting starts the application only once, but you can easily change that, if necessary.

The test case generates user interface events using the JemmyHelper class. The JemmyHelper class also enables access to the state of the GUI widgets. In order to identify user interface elements you have to set properties in you code accordingly.

fFirstName = new ULCTextField();
fFirstName.putClientProperty(TestEnvironment.PROPERTY_KEY, FIRST_NAME);

Test case example

The following example shows how easy it is to write (and read!) test cases. This test case starts with triggering a click on the cell in row 0 and column o of the table. After that it checks whether two text fields hold the corresponding value and whether two buttons are disabled.

private JemmyHelper fJH;

//...

public void testSelection() { fJH.clickOnCell(0, 0); assertEquals("Denis", fJH.getTextFieldText(NameView.FIRST_NAME)); assertEquals("Antonioli", fJH.getTextFieldText(NameView.LAST_NAME)); assertFalse(fJH.isButtonEnabled("Cancel")); assertFalse(fJH.isButtonEnabled("Save")); }

JemmyHelper is a wrapper for the Jemmy libraries. Since it is just a minimal implementation for the purpose of this example you might need to extend JemmyHelper.

How it is implemented

ULC uses Swing to drive the user interface on the client side. However, the server side holds the state of the user interface and enables access to it. This introduces two challenges:
  • Client side and server side are executed in different threads even when using the development runner. Hence, client and server thread have to synchronized.
  • Any access via the ULC server-side API has to be executed in the context of the server session.
The class TestEnvironment solves these problems. First of all, it holds the current UISession. It is initialized by registering a client-side message handler. The server side sends an appropriate message after having created the server-side session. Access to the UISession is guarded since it gets accessed in different threads and the client side might try to get the UISession before the server side has initialized it.

Secondly, the sync() method suspends the current thread until the server side has processed a synchronous user event. The sync() method needs to be invoked before any synchronous user event. This is accomplished before each call of a Jemmy method in the class JemmyHelper.

Finally, access to the server-side API of ULC is done via the executeServerSideCode() method. It stores the code as a Runnable in the TestEnvironment. Then it sends a message to the server side to tell it to execute this code.

Resources

Source code - UITestingWithJemmyExample.zip. Download the required libraries here: - Jemmy, JUnit.