I think anyone will agree that UI testing is painful, especially when the UI framework is closely coupled, there are no interfaces for UI widgets and controls. Every once for a while I try to improve my UI architecture to enable automatic testing with NUnit and one of mocking frameworks. Lately I use an architecture that could be called Domain MVP, it’s somewhat based on general MVP concept (is there one MVP concept?) and a Presentation Model.
Main DMVP features are:
- Separation of domain logic between UI and Business Logic (BL) layers
View is responsible for the UI logic (binding, events, etc), where Presenter does all the BL based operations (also some UI manipulation through IView interface) - Data model is visible to the Presenter and to the View
- Presenter does not know anything of the View controls and widgets (at leas in the ideal case)
- Delegation of View controls properties to the IView interface is limited to the minimum needed by the BL – as opposite to the Passive View.
I the picture above I try to show the main DMVP architecture. Each View class implements a appropriate IView interface and reference the Presenter instance. Each presenter instance reference the appropriate IView implementation. Both View and Presenter know and understand Model classes bu only presenter is allowed to use BL based decisions about the UI, leaving the View to do all the simple and straight forward tasks (e.g. Data Binding).
DMVP is trying to find a compromise between total test coverage of any logic, and writing a minimum of code. I feel that Presenter should not know anything of the UI framework, other than that View can do things that are in the IView interface.
IMHO there are two ways for total coverage:
- Presenter does everything (as in Passive View), then you loose some of the UI framework advantages (e.g. minimum use of design time declarations). You have to delegate everything in the View and your IView interface is full of simple methods and basic get/set properties, so the Presenter does not need to understand and reference UI frameworks classes.
IMHO to much coding. - Presenter does know the UI frameworks classes, some the View controls are are visible through the IView interface. IMHO defeats the purpose of separation and and still during testing you have to somehow mock View controls or initialize them, which is hard to accomplish.
I like 80/20 rule. I think that about 80% of near UI logic is worth testing, the part that is more complicated and BL dependent. Sometimes Data Binding or design time settings can be broken, but these are easy to correct and seldom recurring errors. IMHO it is worth to save time on simple things and focus on BL testing.
I prefer to place test fixture classes near by the BL classes. I think it’s easier to find them and mange them in tandem. Using unsigned mocking (without strong name) forces use of a separate test assembly preferred by some developers. Most of the time I use a combination of those two approaches.