Newer
Older
labs / tiddlers / content / labs / lab03 / _Labs_03_User Interface Testing.md

Testing user interface code is difficult. The input components and handler methods are usually all private meaning your testing code can not access them. The result of executing the handlers is also often not reflected in the user interface --- the changes triggered by the user will often happen in the data store.

To do this properly, we need the tests to:

  • Enter data into the input components (text fields, combo boxes, etc.) on the forms.

  • Execute the click handlers for the relevant buttons/components.

  • Test that the handler did what it was supposed to. This will probably involve checking that the data was correctly modified via the appropriate DAO.

  • Check that the components on the form are displaying the correct details in response to our actions.

Take a few seconds to consider how you could do this. You could make significant changes to the user interface to make everything public --- that might be enough to allow you to get the job done. However this breaks some of the rules of encapsulation. Doing this would be the opposite of refactoring --- making the code worse (occasionally/euphemistically called refuctoring).

If you have not encountered the term refactoring before, it refers to restructuring the code for the sole purpose of increasing the quality of the code without modifying the behaviour of the code. Often the refactoring is about adding abstractions that make the code easier to work with, and easier to test.

Luckily for us there are several libraries that can help us with this.

We will use a framework called AssertJ (https://assertj.github.io/doc/) that allows us to interact with and test Swing GUIs. AssertJ offers similar functionality to Hamcrest --- it provides mechanisms for verifying the state of a system that can be used in automated tests. AssertJ also has a module specifically for working with Swing user interfaces.

The AssertJ Swing module is specifically for testing Swing user interfaces. For web systems, there is a tool called Selenium that can interact with web based user interfaces is much the same way. Most AJAX libraries also provide their own equivalent of AssertJ Swing for testing user interfaces that have been created using that library. Basically, there will generally be some equivalent to AssertJ Swing for whatever user interface toolkit you are working with.

AssertJ helps us with interacting with the GUI, but given that most GUI operations involve a DAO, how do we ensure that the DAO is being used correctly? We already have a set of tests that test the DAO, so doing this again via the GUI is a bit pointless.

We could create a modified DAO that is specifically for testing purposes. It could tell our testing code which DAO methods have been called and what was passed into them.

But we have to create a new DAO from scratch for testing right? Nope. This is what mocking frameworks are all about. They allow us to quickly knock up mock objects for testing purposes. We will be using a framework call Mockito (http://mockito.org/) for mocking our DAO.

We will need to refactor the system to allow the DAO objects to be injected into the dialog classes so that we have a way of controlling which DAO objects are being used --- when testing we will be using mock DAO objects. Using a mock DAO will allow us to:

  • Isolate the GUI classes from the DAO classes. We are now testing the GUI classes in isolation since they will no longer be using a real DAO class that may contain its own bugs which might affect the GUI testing.

  • Use the mock to verify that the GUI is interacting with the DAO correctly. We can ask the mock if a particular DAO method has been called, and then verify that the parameters passed to that method were what we were expecting.