Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


JUnit and Its Extensions Make Unit Testing Your Java Code Much Easier : Page 3

In an age when any professional Java developer has to know how to properly unit test the code he or she writes, JUnit and its extensions can make writing your tests easier and more effective.

Start Writing Your Tests
Now that your fixtures are in place and you've got direct access to the active components on the form, you can go ahead and start writing tests.

Do the Necessary Components Exist?
The findNamedComponent() method on helper, an instance of JFCTestHelper, does exactly what it says: it finds a component with a given name on a given form. This means that you have to name your components. Although you don't usually do this when coding a GUI by hand, it's a good practice—and it's inexpensive. Of course when you use a GUI Builder, naming components is normal.

This is one of the rare instances when changing the code to facilitate a test costs very little, and it doesn't really affect the quality of the code you're testing.

You're going to perform the following six tests on this form:

  1. Test that all the necessary visual components exist on the form.
  2. Test that the form appears with blank input fields.
  3. Test that an error dialog appears if no username and password exists.
  4. Test that an error dialog appears if no username exists.
  5. Test that an error dialog appears if no password exists.
  6. Check that a processing dialog appears if both the username and password are provided.

You'll need to perform a number of other tests too, but I'll leave those as an exercise for you. These tests confirm the form's behavior under the following conditions:

  1. Invalid password
  2. Invalid username
  3. Cancel is pressed
  4. Valid username and password

The first test using the components found in the fixture only checks that they exist:

public void testLogonLayout() throws Exception { assertNotNull(ok); assertNotNull(cancel); assertNotNull(username); assertNotNull(password); }

At this level, where these components are or how they look isn't important - that information can change rapidly as you lay out the GUI. You're only interested in whether they exist. This gives you the freedom to decorate the GUI in many ways—as long as your components exist.

This simple test performs two very important functions:

  1. It confirms that all the components you need are actually present on the form.
  2. It confirms that your tests are working.

Having a broken test can lead to a lot of unnecessary work on production code that may otherwise be fault-free. If you run your form and see the necessary components but this test still fails, something may be wrong with the test.

The next test simply checks that the form is initialized with blank input fields:

public void testInitialState() { assertEquals("", username.getText()); assertEquals("", password.getText()); }

Again, this is a fairly simple yet vital test. You don't want a lazy programmer to initialize these fields with data and then forget to take it out when you ship the product.

Do You Have the Correct Dialog?
Now the tests get more interesting. The next four tests check that the correct dialog box pops up when a user presses the OK button. The four conditions that need to be checked are:

  1. Only a username
  2. Only a password
  3. Neither
  4. Both

To do this, you need a way of setting the text in the text boxes. Because you have direct references to the components, you could just call the setText() method on them. This wouldn't be a good test though, because it isn't driving the GUI in precisely the same way a user would. jfcUnit's helper allows you to send keystrokes to a form to simulate user interaction. Because you need to do this frequently during this example, I've created a private method to make it easier:

private void setText(JTextField field, String text) throws Exception { field.requestFocus(); helper.sendString(new StringEventData(this, field, text)); }

Now that you can set a field's value you can use this method to test the form. Again, because you're basically doing the same thing three times, I've written a method that uses setText(), presses the OK button, and asserts that the correct dialog is showing:

private void checkDialogAppears(String expected, String usernameText,
String passwordText) throws Exception { setText(username, usernameText); setText(password, passwordText); helper.enterClickAndLeave(new MouseEventData(this, ok)); List showingDialogs = helper.getShowingDialogs(main); assertEquals(1, showingDialogs.size()); JDialog dialog = (JDialog) showingDialogs.get(0); assertEquals(expected, dialog.getTitle()); helper.disposeWindow(dialog, this); }

This is sometimes called a check method. The JUnit framework offers no direct support for them, but they're common anyway. Developers use them whenever they need to abstract commonality out of a set of test methods, and that commonality includes the assertion itself.

The checkDialogAppears() method accepts as parameters the title of the dialog and the values for the username and password. It uses the helper's enterClickAndLeave() method to simulate the mouse clicking the OK button. jfcUnit's methods are well named, so the rest of the method should be fairly easy to read. When requesting the showing dialogs a list is returned because there may well be more than one. In this case, you're expecting only one so you assert that this is the case. Then you obtain the title text and assert that it is what you expected.

You use this method in your tests:

public void testAcceptWithBlankUsername() throws Exception { checkDialogAppears("Logon Error: username", "", "admin"); } public void testAcceptWithBlankPassword() throws Exception { checkDialogAppears("Logon Error: password", "admin", ""); } public void testAcceptWithBlankFields() throws Exception { checkDialogAppears("Logon Error: username/password", "", ""); } public void testProcessingLogon() throws Exception { checkDialogAppears("Logging on", "admin", "admin"); }

The tests that I have left as exercises should be quite simple for you to write now, as they're primarily variations on the ones above.

You don't have to write complex tests for authentication on the GUI. If you've followed the MVC pattern, you should have your authorization services in an independent module with its own tests. This means all you have to test on the GUI is that the right dialog boxes are displayed for each error condition, and that the correct page is displayed when the user is authenticated.

jfcUnit makes testing Swing GUIs quite easy. However, it is quite laborious for testing something that isn't likely to break, like your logon box. Ordinarily, you'd save this type of testing for fully interactive forms where the steps are somewhat more involved.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date