I attended Charlie Poole’s When Tests Get Hard session.
The first thing that Charlie said summed XP up for me: “lots of little bits that I’d being doing, but brought together”
Why is testing/TDD hard? A quick poll of the attendees revealed
- no obvious programming interface
- set up time too great, especially for databases
- code in containers or managed by containers can prove difficult to work with
- “Graphical User Interfaces (GUIs) either look good or they don’t”, another fine quote from Alan!
Charlie followed it up with: testing connected sets of objects is hard because:
- tests become dependent upon one another
- objects have to be put into a known state
- it’s hard to figure out what failed
We went on to look at why GUI testing is hard.
GUIs are hard to test because there is tight coupling to other parts of the application, including the business logic. The solution to this is to separate the business logic from the UI, to use interfaces to permit substitution and factories to create business objects. This ran into an interesting discussion regarding the use of interfaces: some folks have argued that using interfaces isn’t the simplest and most expressive “thing”. Charlie believes that they are, on the grounds that they make it clear that a class has a capability. A similar discussion can be found here.
GUIs are hard to test because there is one large program handling all user interaction. Charlie’s recommendations revolved around using separate classes for UI logic and for validation. He also recommended the creation of smart controls (NUnit’s status bar being an example of such a thing – if you have NUnit installed, take a look here: C:\Program Files\NUnit 2.2\src\uikit). The key takeaway from this point was that the forms know too much about the objects that are dropped on them.
GUIs are hard to test because the design is driven by the IDE. Today’s modern IDEs will let you create a form, drop a button on it, double click on the button and write code for the button click. Granted, if you are doing the simplest thing, this is the right place for code, but in the long term it’s the wrong place for code (sure, you’d refactor it out, right?) We should resist the temptation to insert code into a UI just because the UI makes it easy. We should split code into two parts, presentation and behaviour (the use of partial classes and inheritance can help with this). Charlie recommend that we all read or re-read Mike Feather’s The Humble Dialog Box.
GUIs are hard to test because of technical issues of the platform. Charlie reiterated the need to be clear about what testing is needed, i.e. don’t test the platform (except to learn how the platform can help you with your testing), or put other way “don’t test other people’s stuff”
I liked Charlie’s “The Hardness Paradox” which basically stated that if something that is hard to test, it has to be a good thing. This will force us to look more deeply at how are applications are designed, with a view to making them easier to test. Humoursly, we compared this to a bang on the head – were it not for the fact that it hurts, we might keep doing it! Why should we shy away from difficult activities? We’ve cracked TDD for [elementary] classes, now we’re moving on to the next stage: testing the UI, the database, the web service, etc.
Quote for the day:
“If you don’t talk to the customer, the details don’t come up” – Charlie Poole, Edinburgh, 30th June 2005
Lastly, I also had the luxury of joining Charlie, Clarke, Barry and Peter for dinner (Colin joined in but didn’t eat!)
(Oh, and NUnit 2.4 is under development! Can’t wait!)