Testing shouldn't be that hard

| 0 Comments
Yesterday's Practical Testing post was a bit of a mammoth testing exercise. The threaded nature of the component under test makes testing it harder than you'd think; and this is just a single worker thread that we have to worry about. The thing is, I expect that the component would have been designed slightly differently if it had been developed test first; using TDD, or even with just in time testing, (JITT?)...

What I've found recently is that I don't tend to write classes like this one anymore. Recently I've written several classes that had their own threads to run them but I've done it using a relatively simple pattern (small p) that makes it easier to test them: I write them in two pieces. One of the advantages of early testing is that it focuses the mind on the design; TDD especially so. You want to write the tests and you want them to be easy to write; as soon as you end up having to jump through the hoops that we jumped through yesterday you start looking for ways to make the design more testable.

So, the callback timer class would likely have been two classes. The first class would do all the work but wouldn't have any additional threading to manage the timeouts; it would just have a 'handle timeouts' function that you call when you want timeouts to be handled. We could have written all the tests that we've written so far without worrying about threading issues at all...

The second class would have been a 'threaded callback timer' that simply added a worker thread that used functions on the non-threaded object to create the automatic polling of the timeout handler. This would be easy to test because we could focus on testing the behavior of the polling loop and ignore the complexity of the timer queue object. In all honesty the polling loop is likely to be simple enough that we don't really need to do much to test it; write test 1, eyeball the small amount of code and be ready to write test 2 if it breaks in production... If we do want to be able to test the polling loop easily we could have the threaded callback timer take a 'call back timer' interface so that we could mock out the timer object...

I've been finding that since I've been using TDD and JITT I end up with many more classes than I used to have and each of them does less. Cohesion is up, coupling is down, functionality is split in a more orthogonal manner and the objects appear to be easier to reuse; the callback timer above could be driven by an event driven system rather than a threaded polling loop; or driven by a gui button press, or whatever. The downside is that these objects tend to require composition before they can be used; I seem to find that I have a layer that consists just of wiring together objects from lower layers. Its sole purpose is to do the parameterize from above thing and take a collection of parts and build usable objects that are appropriate for the domain at hand; such as what we did with the CTestCallbackTimer in yesterday's posting.

So, testing shouldn't be as hard as it was for us yesterday and it only tends to get that hard if you practice bolt on testing (BOT? ;) ). With TDD or JITT you end up with easier to test code and more flexible designs.

Leave a comment