A long day of unit testing
I was writing some code which archived a list of files into a specified directory. As a supporter of unit testing and Junits I was keen to get some tests to see if my code was working. I actually wrote the test before coding the method. I won't bang the unit test drum today but needlessly to say if you haven't worked by writing the unit test first and then writing your code, I highly recommend it. The one thing that always amazes me is the amount of small syntax and silly code the tests catches and it's a lot easier to catch when you are just testing one method at a time rather than trying to find the problem in a piece of code which nips in and out of 30 methods
Back to my unit tests. To correctly test the code was working correctly I had to do a fair bit of ground work creating a small directory structure and then putting a file in it and finally archiving the file into another directory. This is where sometimes you question all this unit testing stuff but I stayed with it and then I got it working and found a few bugs and then felt my code was in good shape.
The only nagging problem I had was that the tests weren't working every time and if one of the tests broke it was effecting the other tests. It was linked to the way I was deleting the folders and files I was creating for the tests. If it failed one of the tests then it wasn't cleaning up after itself or wiping it's feet on the way out. Damn I was close but not close enough.
I started off making the File(s) of the directory's I was using and then doing a File.Delete() and testing to make sure they didn't exist but I didn't feel this was the right way to go about it because it was then the next test, testing the previous test had worked correctly. I knew this was bad so I went for a tea break and then came back determined to sort this test out. I decided that each test should clean up after itself, the reason why I didn't do this before was because if any of the tests failed it didn't always reach the bottom of the test where the cleaning up code was. What I needed was a finally block to do the cleaning up and remembering some stuff from SCJP exam (who would have thought it would actually be useful). Remember some information about try and catch blocks, I remembered I didn't need the catch block and could just put in a try and finally block. So this is what I did and now all the tests are happily cleaning up the files they used. Success.
So once I got the main test working I added a few more which caught some more bugs and I finally I had my code and had it tested. Another interesting nuance of writing unit tests is that I tend to write smaller methods test them and then use a few smaller methods to create a bigger methods, which fits in with my recent blog entry
One of the by products is that I write a small method test it and then write a bigger method using a few smaller methods. When I then need to write a method which does something similar but different I can often quickly build it up by using some of the smaller tested methods and just a change a few methods. Writing smaller methods gives you building blocks.
So that was my battle with unit testing yesterday and one point it did feel that I was doing quite a lot of work and not actually writing any production code but in the end of the day I felt it was worth it. Firstly I created some tests which are independent of the correct folders being on a machine that runs them and secondly I tested the code and found a number of bugs, which I was glad that I found them early on when I was only testing one method and hence quickly found the problem. Once you test a method and are happy that it does what it should it gives you confidence that any other problems are unlikely to be caused by that bit of code.
The way I think about writing unit testing is it's better to spend the time writing tests than spending time debugging the code later because writing unit tests is 99 percent of the time quicker than debugging the code at a later date.
4 Comments:
"The way I think about writing unit testing is it's better to spend the time writing tests than spending time debugging the code later"
Yes, fine, but I'd much rather spend the time writing better code in the first place.
For example, I'd rather use polymorphism instead of casting/instanceof, because the compiler will catch my mistakes, and I get a compiler for free, whereas writing tests that verify the code takes energy.
Cheers.
By Ricky Clarkson, at Wed Oct 04, 02:06:00 pm 2006
I'd love to see this article on http://en.eioba.com .
By Anonymous, at Wed Oct 04, 03:07:00 pm 2006
"the tests weren't working every time and if one of the tests broke it was effecting the other tests"
I always try to make the tests atomic, ie they can not rely on other tests behaving well. I have done similar unit testing as you have, with files and directories. If I remember correctly I used the setup() method to create a random base folder. This base folder was then the base for all new files, etc I had to create and delete. Then I used the teardown() method to remove that base folder. This would let every test start fresh with an empty folder.
I wish the current project Im working at now, would have used unit testing because many of the problems would have been found there and not by the customer.
By redsolo, at Wed Oct 04, 04:11:00 pm 2006
I couldn't help but think of Michael Feather's definition of a unit test while reading this article:
http://www.artima.com/weblogs/viewpost.jsp?thread=126923
Unfortunately, the Java libraries don't make it very easy to do real unit testing of code that uses them. All the same, I find useful to make the distinction. It helps keep us from slipping down the slippery slope to a big blob of unreliable, slow system tests masquerading under the name 'unit tests'. ;)
(if you want to know what I mean by unreliable, run one of your unit tests in a debugger and kill the JVM when you've stopped at a breakpoint) :)
By Ryan Cooper, at Wed Oct 04, 09:59:00 pm 2006
Post a Comment
<< Home