Testing UI – part 1

Lately I have been getting a lot of questions on how to test User Interface(UI) code. People always claim that UI testing is very hard or even that it is not possible. I think that with the right kind of design, UI testing is just as easy as testing any other piece of code. Let me show you how I do unit-testing of UI in Adobe FLEX which uses ActionScript as its programming language.

Lets say we wish to test a common UI component such as a login page.

The important thing is to separate the graphical UI from the control logic and data. This can be achieved with the standard Model View Controller design pattern. Where Model is the data (username/password), View is the visual components (TextField, Button) and Controller is what glues the pieces into an interactive UI (What happens when I click Login button.) However, from testing point of view there is one important caveat which can not be broken! The source code dependence must be expressed in following order.

View -> Controller -> Model

In other words Controller and Model can never know about the View! Neither direct or transitive dependencies are allowed. (i.e. Controller knows about X and X knows about View is just as bad as Controller knows about View). Similarly the Controller knows about the Model but model does not know about the Controller (although that requirement is not as strict.) Often times I merge the Model and the Controller into a single class if I don’t expect any reuse of the Model. Such as in this case of a login page.

Notice how closely the Controller mimics the actual UI. Each entry field gets a field, each UI state (showError) gets its field as well, and finally each action gets a method. Also notice the [Bindable] annotation which allows any class to listen to modification in object state. In out case we want the View to be able to listen to state changes of the Controller without the controller explicitly knowing about the View.

Notice that the View has a direct access to the controller Also notice that all of the TextInputs are bound to the corresponding fields on the Controller (In ActionScript the {controller.username} mans that the value is bound at runtime to the destination. Meaning any changes in username/password will be reflected in the text fields.) Because ActionScript data binding is not bidirectional, we also register change events on the TextInput which which copy any changes in the UI back to the controller. We then bind the “Login” button to the Controller login() method. Finally we bind the error message “Login Failed” visibility to controler.showError.

All this binding achieves that the Controller is fully separated from the view. So from now we can forget about the view and just worry about testing the Controller. Now many people will argue that I still can have errors in the wiring / binding process. True, but from my personal experience most errors are in the logic not in the boring wiring code. The wiring code either is broken and it does not compile or it compiles and chances are it is right. By ignoring the wiring and the graphical portion of the UI It is unlikely that I have left too many bugs in the code. Also even if I test the View I still don’t know if it “looks right” which only a human can do. So I simply take a very pragmatic approach and draw the line at the View. I get 90% of benefits with very little cost. Turns out that there are scenario based frameworks out there which will allow you to write test with full View code coverage, but those are not unit-tests and hence I will not go into them here.

As you may have guessed the Controller will mimic the View very closely. This is actually very desirable as you don’t want to have “impendence mismatch” when trying to do the wiring. Any “impendence mismatch” will result in marshaling code which may turn your simple binding problem into a hidden controller and hence moves logic from the true home of Controller into the bindings/view which is undesirable.

Notice the since the Controller mimics the View the Controller forms a kind of a domain-specific-language (DSL) which is actually very useful in scripting serration tests and also in understanding what the test is doing.

Finally lets look at one last thing, and that is how the whole thing is wired up. Your controller will need to collaborate with your application service objects. This implies that the control is dependency-injection (DI) heavy and should therefore be injected into the view. As usual you will need a single top level factory which instantiates all of the services, Controllers, Views and service and then inject all of the references into appropriate places. Here is the FLEX equivalent of the “main method”.

I did not get it about Model-View-Contoller. You say Controller shouldn’t be dependent on View, but aren’t contollers exist exactly for briding views and data, and interfacing them to rest of the system? Programs I worked with had dependencies like this:

ViewModel

How does view know what visual elements it’s to change when model changes? Via observing model’s events? Or how?

I am sure in the bast you have seen the dependencies go all different ways. But I bet you those ones are hard to test.

A View is rendering, that is hard to test. Unlikely that you will be able to assert anything interesting. Not to mention since it is rendering it needs some graphics context and so it will not be a unit test.

A Controller has lots of interesting code/behavior in it which you want to test. But if controller knows about the view than Controller is now hard to test since dependencies are transitive. That is why we need to break that dependency.

Now you are right, we need to be able to communicate data from Controller back to UI. So to do that we use data bindings. (Or events). This way we can easily unit test the controller and don’t have to pay the expensive view set up.

Now many systems have this backwards, or even have circular dependencies. My guess is that those systems are also not easy to test.

This is a good presentation of a controller communicating with a view using data binding. But I have two concerns. One thing I do not like about data binding is that it can lead to subtle bugs regarding time. That is, when you have multiple data items that work together, you want to be sure that all of them pertain to the same entity. For example, that they all belong to the current customer, not a previous customer that the user clicked through. The other concern I have is with complex user interfaces. If there is some complex manipulation of the user interface, that requires more that just accessing the text property of a UI component, such as creating additional components on the fly, the programmer would have to decide how to allocate the code between the view and the controller. That might make for some difficult decisions. It might also tempt the programmer to have the controller access the View. In any case, thank you for the presentation.