Shout Out to Model View Presenter and Passive View
I mentioned last week that I'd talk about GUI testing, so I suppose I should. GUI testing is generally regarded as hard. In my case, I've mostly had to deal with Java GUI code. There are a few things I can think of to aid in testing GUI code (there may be further ways or angles, too, which I'd love to see discussed if so)
- Keeping code modular and well encapsulated
The usual good coding habits help a lot here. This is mostly the obvious splitting the duties of code (a la various MVC inspired patterns). There are some improvements over standard MVC, though. Model View Presenter, for instance, is really sweet. Currently one in-house favorite is to have a PresentationModel / View, which is a variation of that.
- Minimize the amount of GUI code to test (make a view that doesn't have any real logic to test)
This is where Passive View comes in. Passive View is pure awesomeness. (why did I ever write views any other way...) There's very little to test if your view doesn't DO anything but display GUI components and have action handler calls. In Passive View, it's illegal for the view to ask for anything. All data is pushed to the view, it does not 'request' anything. The only permitted calls are action handler methods for when GUI components are interacted with. This action handling can even be turned into an interface, so that the view doesn't even have a real reference to the presenter/controller/etc (pattern-dependent).
Your 'OK' button not doing anything is very rapidly found even without automated tests, so as long as the real logic (which is completely absent from the view) is well tested, you are in good shape.
- Using GUI testing frameworks (like Abbot) that simulate a user. There are similar frameworks for testing webpages...
It is possible to do automated testing of GUIs even if the first 2 items need work or are deemed insufficient. We use Abbot to automate GUI testing of important parts of our application. The tests run the same way other JUnit tests run. Most would deem these functional (not unit) tests, and I agree, because the time impact of powering up a real GUI (especially one you can't disconnect from your system) and physically typing input and clicking buttons is very noticeable.
Generally, lack of encapsulation and too many dependencies are again a real hinderance and bog down GUI testing. If you can mock out or easily disconnect the GUI from the usual, live system, then speed should be less of an issue. So with proper effort invested in 1&2, I aim to get #3 in the general ballpark of unit test times. I don't think that, following 1&2 strictly, I would write a large amount of abbot tests, but I want to try proving it's possible to have nice, isolated and relatively fast GUI tests if you want them. Maybe I'll do some speed/effort analysis on this at some point - because I'm that much of a geek.