Better Software through Testing
I already knew that unit tests were a good thing and gave you an increased level of confidence in your code. But I always found them hard to apply in real projects because I rarely spend my time developing code libraries or console apps. The typical business applications that I work on have a GUI front-end, some business logic, and a backend database. The problem is that most of the normal testing is done manually through the GUI.
In this article, Will Stott and James Newkirk, describe a different mindset developers should take when writing code that is to be unit tested. In a sense, the GUI should be transparent and you should create interfaces that can be used by both the GUI and can be auto-tested.
But there’s still the problem with testing the functionality of the GUI. For example, what if you want to make sure that:
- drop downs were properly populated
- the user was correctly authenticated
- your tree is rendering correctly
- clicking on controls results in the expected action
- different users get their own data
Excerpt from article:
Using TDD in the Real World
One of the first things to consider when using TDD since a commercial project is deciding how to organize your programs so that the production code can be easily separated from the code used to test it. You want to run your programmer tests throughout the product’s development and yet be able to easily remove them for the purposes of releasing the code.
Another issue you might encounter is the difficulty of testing GUI applications driven by mouse and keyboard input. For example, how do you write a test that simulates a user clicking a dropdown list and then verifies that it is populated with a given list of country names?
The answer to both of these problems lies in dividing the code into appropriate components that can be built, tested, and deployed separately. For example, rather than building Quad as a class contained in the same executable file as the main application, it could have been contained in a separate library (.dll). This would have allowed us to develop both the test program and the domain program as separate executables (.exe) that shared a common library (.dll) containing Quad. Note that if you’re only building a library, NUnit and your test suite can be used as the interface, rather than requiring a separate harness.
The idea of keeping the main program very simple and putting the business complexity into classes contained in a library can also help solve the problem of testing GUI applications. One of the rules of TDD is that you don’t test third-party code, so there is no requirement for you to test the GUI framework classes, although it’s sometimes useful to test interfaces, particularly if they’re a bit flaky. This means you can catch the user event in a class that you know works and then pass it through for processing to the class you’re developing. Again, you can separate the test program and the domain program into separate executables sharing the common libraries that form the bulk of your development effort.