Belongs to following categories: Integration, ULC6.1, ULC6.0,
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.
Resources
The example code can be downloaded
here. Download the required libraries here:
Jemmy,
JUnit.
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.
Author
bruno