My Crackpot Idea for WinForms Development

Automated testing, especially at an acceptance level, can be a bear with WinForms applications.  On my last project we effectively abandoned integrated FIT testing against the UI.  We tried to go down a path of writing Window Driver‘s against each big control, and driving that through FIT & NUnit tests with NUnitForms.  It just turned out to be too much work, too much duplication of information, and just plain laborious. 

There are definitely some things you can do to enhance testability.  The various flavors of Model View Presenter come to mind immediately, but that can easily bring on some repetitive coding around filling dropdown lists, validation, and coordination with views. 

I’m going off the beaten path in my new WinForms project.  I’m ditching WinForms data binding altogether because it plays utter havoc with automated testing.  Instead, I’m building my own programmatic data binding that effectively embeds a Window Driver class directly into each User Control.  The “ScreenBinder” class is configured programmatically with a fluent interface (Martin says the best way to understand the limits of a technique is to overuse it;). 

I’m trying to kill 4-5 birds with one stone:

  • That fluent interface contains grammars to declaratively attach properties of the model class to elements on the page.  In effect, I’m recreating data binding, but in this approach I’m going to have explicit control over when things happen.  No more goofy hocus pocus focus stuff to get data binding to fire inside tests.
  • The ScreenBinder will also double as a Window Driver that I can use inside automated tests to find screen elements by either the bound field name or the attached label name.  I’m already building a reusable DoFixture right off the bat that can act as the foundation for a testing DSL to express screen requirements in automated tests.  On my previous project we were routinely killed by “oh yeah, this element should default to XYZ when ABC happens like the legacy system” type of requirements.  This time around I want to be able to capture that stuff upfront in human readable FIT tests that can be run in the automated builds.
  • Declaratively add minor screen behaviors like filling a combo box with data from the service layer with a grammar like “Bind(SomeConstantClass.Category).To(categoryComboBox).WithLabel(categoryLabel).FillWithList(ListType.Category)”  Basically, I’m hoping to have a single abstract method that’s overriden in each UserControl that declaratively defines much of the behavior of the screen.  One of my design goals is to be able to quickly understand the behavior of a screen largely by reading through this method.
  • Wait, you’re putting more behavior in the screen!  Isn’t that wrong?  Well generally I’d say yes, but the underlying goal is to make code easy to write, change, read, and test.  I’m using what I call the “Micro-Controller” pattern to define little reusable controller classes to drive one element at a time.  Those little micro-controller classes can be TDD’ed to my heart’s content.
  • I’m building a quick test harness with NUnitForms to make declarative assertions against one of my BoundControl’s for common functionality.  I’m figuring that by making the screens easier to test inside of NUnit that I can get away with thinner Presenter’s.  I’ll probably go with a Supervising Controller for more complex logic and dealing with the service layer.
  • The ScreenBinder ends up being a great way to bind declarative validation rules to the proper screen elements.  I simply capture a Notification object that relates validation messages to the property of the Model class.  The ScreenBinder knows the correct element for a given Model property, so it’s not that hard to go the extra step to attach validation messages to the proper screen elements.  On my last project one of my client developers built something similar to the new Validation Block that used attributes on our domain model classes to enforce validation logic.  We did use the BindingSource on the screen to attach validation messages to the proper screen element.  I’m going to do the same thing here, but use a Notification object in between to make validation logic easier to test.

So, the question I ask you, gentle reader, is how crackpot is this idea?  If it works I’m thinking about harvesting a new OSS project out of this work (after DevTeach and a solid StoryTeller beta and assuming that the client is okay with it).  Otherwise, if I never post about it again it’s a good bet that it failed. 

There’s no possible way that it would fly with my client, but I wonder how much better this approach would be if I could drive the UI with the RubyCLR bridge so I could use the declarative ActiveRecord validation scheme and symbol.  I think the Fluent Interface approach would be more effective in C# 3 with the ability to use extension methods to add application specific additions to the fluent interface.

I’m working solo at the minute, but I’m going to be joined by another Finetix developer soon.  One of the first things I’m going to do when he onboards is get his opinion on the “novelty” portions of my envisioned approach.  If that approach doesn’t fly with him, it probably gets scrapped.  And if he’s enthusiastic, then we still need to be careful because then we’re just guilty of group think.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Jeff,

    It is released on google code. Look for the “shadetree” project. I’m using it a little bit, but it’s abandoned otherwise because I’m not doing much WPF or any WinForms now.

  • http://www.agilification.com Jeff Doolittle

    ah, build your own CAB #15 seems to be it. never mind.

  • http://www.agilification.com Jeff Doolittle

    any chance you’re still considering building this fluent approach to winforms databinding?

  • todd

    Are you going to provide any more code samples? I have a project where we need to do a basic level of gui testing through Fitnesse.

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Mladen,

    I kept going with the data binding replacement. It’s still the Supervising Controller variant of MVP where the Presenter does anything complicated. I went ahead and built the fluent interface to describe the data binding and some of the simpler forms of the screen behavior. I think the fluent interface is too verbose and we’ll trim that down. Otherwise it’s full speed ahead.

    The only really cool thing is that it has opened up the screen itself for easy testing. I’ve already written a FitNesse fixture that drives a screen through my data binding replacement like this:

    !|TheScreenFixture|
    …some application specific stuff to start the screen
    |Enter| [Control Label1] |Value|100|
    |Enter| [Control Label 2] |Value|25 |
    |Check|Value Of| [Control Label 3] |Is|2500|

    The FitNesse fixture is running against only the view and presenter with everthing else stubbed. I’m not even firing up NUnitForms yet, so the tests run sub second. The app I’m building is going to have tons of this kind of screen logic, so it’s advantageous for me to have this.

  • http://weblogs.sqlteam.com/mladenp Mladen

    so what did you ended up doing?

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Steve,

    I’ll definitely go check out your post.

    “Information such as what type of control to display for a particular field, or what dropdown list to display is captured in my O/R Mapper definitions. Thus, I can display a field consistently no matter where it is, and have no need for capturing that at the form level.”

    I’ve flirted with that several times, but I just don’t think WinForms is very good with dynamic layout. I have done that years ago in a heavily DHTML screen with JavaScript.

  • http://dukeytoo.blogspot.com Steve Campbell

    See my solution at http://dukeytoo.blogspot.com/2007/04/testable-ui.html

    I am in favor of dumb forms, with no code. If there is code, then programmers will add more, and pretty soon you will have autonomous, untestable forms.

    I have a similar components to what you called ScreenBinder. One is called Screen, and the other is called Binder. Screen provides design-time support for associating widgets with data. Instead of a fluent interface, the information is just captured in the property window at design time. Thus, the code-behind is completely empty, except for the hidden Windows Form Designer section.

    My Binder component just provides run-time support for data binding.

    Information such as what type of control to display for a particular field, or what dropdown list to display is captured in my O/R Mapper definitions. Thus, I can display a field consistently no matter where it is, and have no need for capturing that at the form level.

  • Carlton Nettleton

    I am not sure what you are trying to automate. Are you trying to automate the actual clicking of the UI widgets that usually passes for traditional plan-driven testing? Or are you trying to automate that when an event happens, the UI state is changed?

    If you are trying the first, then I think you are reaching the limits of automated testing. If you are trying the second, then I think you are over-engineering the problem. Take a look at the Mediator pattern. I have had a lot of luck with this pattern to help with UI controls. Basically, you register all your controls with the mediator and then call mediator methods to change the state.

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Ian,

    I’m not going to automatically synchronize the UI to the Model or even try to put “ThingChanged” events off the Model. I’m not expecting any scenarios like you’re describing though. I’ve just got a system that’s eventually going to collect 20-50 slightly different data entry screens.

  • http://www.ringrose.name Ian Ringrose

    I have had thoughts along similar lines, but have not had a project that justifies implanting it. How does the new data binding system in WPF change the trade offs?

    I have always thought that data binding should be great for TDD, but it has never seem to live up to what I expected from it.

    A issue that you do not seem to have address is what happens when a method on a domain object changes a property 100s of times, how do you stop the UI updating 100s of times? I have had to use timers in the past, so as to only update the UI after control has returned to the message loop.

  • http://www.feedghost.com/ Stu Smith

    Hi Jeremy,

    In my previous job we decided to leave behind the standard WinForms databinding and roll our own – and it worked really well. Essentially, instead of the usual Get/Set methods for each field on the business objects:

    string GetName() { … }
    Void SetName( string s ) { … }

    And binding to those, we encapsulated each one as a property:

    StringProperty Name { get { return _name; } }

    Where StringProperty contains the get/set methods instead. This gave us a really nice event mechanism: not only could the UI push to the business objects, they could also “push” back: the property classes also exposed whether the property was amendable, a validator, and various events – in short, everything the interface needs to know what’s going on with each property.

    In the user interface, we had corresponding databound controls (StringControl to follow the example), where you simply set the .Property to the business object property, and everything was bound up, eg

    _nameControl.Property = someBusinessObject.Name;

    So for an example, if you had a Boolean that controlled whether another property was enabled, the event sequence was something like…

    UI: user clicks checkbox
    UI: boolean control sets value of bound Boolean property.
    BO: Boolean property fires event on its containing business object.
    UI: String control, which is listening to the same business object, updates itself, and find that (via the BO rules) it should enable itself.

    The really nice feature is that all the business logic really is in the business layer: no need to attach an event to the checkbox in the UI to enable/disable the other control. In fact many simple were nothing more than:

    void Show(SomeBusinessObject someBO )
    {
    _firstControl.Property = someBO.FirstProperty;
    _secondControl.Property = someBO.SecondProperty;

    ShowDialog();

    _firstControl.Property = null;
    _secondControl.Property = null;
    }

    (Oh and I should mention we used an object-relational system that handled in-memory transactions, so a dialog had a transaction around to handle OK/Cancel buttons).

    And so testing: we then had a very simple scripting system that ran from inside the application (on idle), which had commands such as Click, WaitFor, EnterText, etc, which identified named controls in the WinForms control tree and performed various actions.

    Because we had rolled our own databound controls, there was no need (like you say) to fudge focusing: when the scripting system set the .Text on a StringControl, it would set the value in the business object, and any events would make sure that the UI updated exactly as if the user had initiated the change.

    Stu

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Steve & Mladen, Wow, thanks for the links. I will certainly check them out.

  • http://weblogs.sqlteam.com/mladenp Mladen

    I’ve taken a different step with nunitforms.

    I take an already built and compiled application and test that like this:
    http://weblogs.sqlteam.com/mladenp/archive/2007/03/01/60123.aspx

    i must say that it works great.
    With this approach you can test everthing just like if a user clicks the GUI.

    I’ve also auto generated a class using CodeDOM that creates a tester hierarchy on the controls in the assembly. so when you compile your tests and you change controls in your project your test project will get a build error.

    our current app is heavily multithreaded and it’s easily testable.

    hope this helps.

  • http://www.stevetrefethen.com/blog Steve Trefethen

    Hey Jeremy,
    I enjoy your blog and thought you might be interested in some of my posts on the topic of GUI automation. I’ve blogged about automated GUI testing of Delphi’s VCL framework (of which WinForms is very similar) and the Delphi IDE itself using Borland’s Zombie (internal) test framework. Here are a few links:

    Posts on Zombie:

    http://www.stevetrefethen.com/blog/CategoryView,category,Zombie.aspx

    Automation posts:

    http://www.stevetrefethen.com/blog/CategoryView,category,Automation.aspx

    Video of Zombie automating the Delphi IDE:

    http://www.stevetrefethen.com/blog/ScreencastOfWindowsTestAutomationOfTheBDSIDE.aspx

    Many of the ideas discussed could be used to build a framework for WinForms testing.

    Good luck!