UISpec4J - NetBeans Example


UISpec4J is an Open Source functional and/or unit testing library for Swing-based Java applications, built on top of JUnit.

Prerequisites


JDK 1.7
Download the Accumulator project Zip file: Accumulator.zip
Unzip the file.
If you don't want to use the NetBeans IDE, you can run the corresponding Ant targets from the command line.

Accumulator application

Run the application

  1. Start NetBeans 7.3.1.
  2. From the menubar select File > Open Project and navigate to the Accumulator project folder.
  3. Run the project.
    screenshot
  4. Type "7" in the text field and click the "+" button. The Total field will change to 7.
  5. Type "3" in the text field and click the "-" button. The Total field will change to 4.
  6. From the Help menu select About.  A popup dialog shows where an About message will appear. Click "OK".  Close the application.

SwingView class

  1. Open the SwingView class in the editor.
  2. SwingView has a constructor, three actionPerformed methods, and a refresh() method.
  3. Observe in the constructor that each Swing component has been given a name using the setName() method. This is necessary so that UISpec4J can locate the component at runtime.
        txtEntry.setName("Entry");
btnPlus.setName("Plus");
btnMinus.setName("Minus");
txtResult.setName("Result"


UISpec4J Test classes

The application contains four sample unit tests that demonstrate different features of UISpec4J.

SimpleTest

The simplest kind of GUI test you can write.
It creates an instance of a JFrame (line 3)
Locates the text entry field using the string we assigned the component with setName().(line 6)
Places some text into it (line 7)
Locates the plus button (line 8) and clicks it (line 9)
Then makes an assertion about the content of the results field (line 12). 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public void testAdd()
{
SwingView view = new SwingView();
/* Note: Window, TextBox, and Button are UISpec4J classes */
Window win = new Window(view);
TextBox entry = win.getInputTextBox("Entry");
entry.appendText("5");
Button plus = win.getButton("Plus");
plus.click();
TextBox result = win.getTextBox("Result");
/* Standard JUnit assert */
assertEquals("5", result.getText());
}
Three things to note about this simplest kind of test case.
 * It extends JUnit TestCase, not UISpecTestCase.
 * Therefore, it uses standard JUnit-style asserts,  not the UISpec-style.
 * It instantiates just a single GUI frame; it doesn't run the application main method.

NormalTest

This test extends UISpecTestCase.   As a result, it can use some special forms of assert that can directly interrogate the UISpec4J components.
Line 6 asserts that the window title bar is displaying a particular string.
Line 13 asserts the result field text is displaying a particular string.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public void testAdd()
{
SwingView view = new SwingView();
/* Note: Window, TextBox, and Button are UISpec4J classes */
Window win = new Window(view);
assertTrue(win.titleEquals("Calc"));
TextBox entry = win.getInputTextBox("Entry");
entry.appendText("5");
Button plus = win.getButton("Plus");
plus.click();
TextBox result = win.getTextBox("Result");
// UISpec-style assert
assertTrue(result.textEquals("5"));
}
Three things to note
 * It extends UISpecTestCase, not JUnit TestCase
 * It uses special UISpec-style asserts.
 * It instantiates just a single GUI frame; it doesn't run the application main method.

AppTest

In a more complex application you might want to test the entire GUI by running the application's main method, not just a single JFrame.  To do that, call the setAdapter() method inside setUp() (Line 3). Then in line 8 call getMainWindow().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    protected void setUp() throws Exception
{
setAdapter(new MainClassAdapter(Main.class, new String[0]));
}

public void testAdd()
{
Window mainWindow = getMainWindow();
/* Note: Window, TextBox, and Button are UISpec4J classes */
assertTrue(mainWindow.titleEquals("Calc"));
TextBox entry = mainWindow.getInputTextBox("Entry");
entry.appendText("5");
Button plus = mainWindow.getButton("Plus");
plus.click();
TextBox result = mainWindow.getTextBox("Result");
// UISpec-style assert
assertTrue(result.textEquals("5"));
}
Three things to note
 * It extends UISpecTestCase, not JUnit TestCase
 * It uses special UISpec-style asserts.
 * It instantiates the application main method.

PopupTest

This test demonstrates the ability to intercept a dialog that pops up at run time, interrogate its fields, and then close it.  Refer to the UISpec4J documentation for the details of this technique.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    /* This is needed for the next test, otherwise the dialog is displayed 
instead of being intercepted by UISpec */
static
{
UISpec4J.init();
}

public void testAbout()
{
SwingView view = new SwingView();
Window win = new Window(view);
// Select About from the Help menu and
// Check that the About box displays properly
WindowInterceptor.init(win.getMenuBar().getMenu("Help").getSubMenu(
"About").triggerClick()).
process(BasicHandler.init().
assertContainsText("About").
triggerButtonClick("OK")).run();
}

Execute the tests

  1. Right-click on the project node and select "Test"  (Alt-F6). 
  2. The four tests should all pass.  (You may get a warning "Cannot convert string ... to type FontStruct" that can be ignored.
  3. Note that the tests don't run quite as fast as a typical JUnit test, because there's a lot of reflection and graphics stuff going on in the background that slows it down.  But it is much faster than a "record-playback" style test (E.g., Costello).

Troubleshooting

If running the test produces this error:
java.lang.UnsatisfiedLinkError: sun.awt.motif.MToolkit.init(Ljava/lang/String;)V
you probably aren't using JDK1.7 as specified in the Prerequisites.

On some machines running the test may result in an error:
Can’t load library: /usr/lib/jvm/java-6-openjdk/jre/lib/amd64/motif21/libmawt.so
In the CSL labs on CentOS, this is because a Motif library is in the wrong location. 
One workaround is to use Sun's JDK instead of Open JDK. Start NetBeans from the command line and point it to the Sun JDK installed in the instructor's grader account.
/usr/local/netbeans-6.9.1/bin/netbeans --jdkhome /home/graderjd/jdk1.6.0_30


A second workaround is simpler but may not work in all situations. Open a terminal window and type this line:
export AWT_TOOLKIT=XToolkit
Then you can type "ant test" to run the tests at the command line, or you can start the NetBeans IDE with the appropriate command.



Suggestions to improve this page? Send feedback.