Tuesday, February 15, 2011

Test Driven Development

It has been some time since my last post, work has been rather hectic of late.  My downtime has been just that, downtime.  However when I finally got back to my Java oData Consumer I ended up having a good experience in Test Driven Development that I thought I would share.

The next small chunk that I wanted to complete was the XML namespace to package name piece, and then applying that package in my code when trying to get a type of node from a known namespace.  The first part was easy, I wrote my test, got the code working, and vola, I had my XML namespace to package converter.  Not the best work, has hardcoded parts that I would love to remove, but it does the job.  It is something I can refactor later once I have a complete oData consumer.  (A side note, I can add various namespaces and XML definitions easily, so am thinking of also expanding this to allow for a simple RSS consumer in Java, but that is way down the track and I digress.)

The next part I thought was simple. Combine the package name with the expected class name and end up with a complete class name that I can reference in my code when I am trying to create a new node in my tree.  I wrote my test, got it working, then because I had tests that checked the rest of the code I ran those and lo and behold they broke.  So, I fixed them up making sure that I was not breaking anything else, and my code went back to being robust.

The reason why I am saying that this is a good experience in Test Driven Development (TDD) is that if I did this the way I am used to, just manually tested my code, there is almost no chance that I would have picked up the bugs that I created.  By using TDD I had a repository of tests that I have coded against to meet the requirements (each in and of itself a small requirement).  Now I might not have hundreds and thousands of tests to run against my code, but as my codebase grows, the number of tests expands as well to cater for the new code.  No new code should be written where it isn’t to make a test pass.

However, proceed with caution here.  Tests need to be useful and meaningful.  Make sure that you are testing what you think your testing.  Your tests form part of your codebase, make sure you check that they pass regularly, and also make sure that you know what they are testing.  Having heaps of tests that are checking the same thing is pointless. If you have one test to check that your function is working in a set scenario, then move on.  You should write a new test for each scenario.  Also you when you get a bug you should be able to write a test to show that the bug is in the code, then you can debug your code to make sure that the fix is working, and that it hasn't accidently broken anything else.

A tip on testing that I got from Tatham Oddie (@tathamoddie on twitter) is to use the following template for writing a test.  It works in any language.  First create the test (the name and container in code).  Then add 3 comments: Arrange; Act; Assert.  The first part of your test should be to Arrange the objects that your testing, with mocks, creating the object that you want to test.  The second should be the Act part, this is where you perform the function or method that you want to test.  The third is the Assert part, where you check that what you wanted to be the result was indeed the result.

No comments:

Post a Comment