Primarily Vinod's techno babble and secondarily his rants and hopefully some useful insights. A medium intended for learning by sharing experiences to hone programming skills and hopefully also network with like-minded enthusiasts.

Saturday, July 24, 2010

Having ANT talk to SVN for sophisticated Unit Testing

Recently I encountered a situation where there was a requirement to execute only newly written JUnit tests for the product. For some inexplicable reasons the team had gotten into an undesirable habit of not unit testing. Some of the older JUnit tests that were written a few years back by a different set of people were broken or irrelevant and nobody in the team had the time or inclination to go through the old ones and understand them, leave alone fixing them. That is pretty much an understandable human characteristic? After all, how many times have you wanted to take a closer look at code that you might have cranked up an year earlier?
Another reason for wanting to discard the older tests was the need to measure the effectiveness of the new processes the team had adopted on the code quality. I am thinking it would be a nice idea to also track the effectiveness of these new changes on a release-by-release basis. If the code-quality trend was improving, then we would know for sure by some quantitative measure, the effect of the process changes that the team had embarked on. Let me make a guess, you are now wondering what new changes we were doing to our style of working.
  • For all newly added classes all public methods will need to have unit tests
  • For any modified code if the method signature was public, a new test would be written or if there was a pre-existing test, it would be corrected to be meaningful in the current context of the method in that class
  • Code reviews by senior engineers in the team who really know they stuff. The intention was to cover at least the services that were being exposed. The UI and controller layer code are being given a lower priority for now. That decision will probably be revisited in the future iterations.
  • Create a more harmonious environment of learning and competing by honing one's programming skills. This seems to be the toughest challenge!
Having decided on the 'what' to measure part, the next obvious step was to figure out the 'how' part. I identified that given a time line range for a release, I needed to know
  • all the modified classes
  • all the newly added classes
  • all the newly created tests
  • all the modified tests
Armed with these information, I planned to execute only those junit tests that were of interest to me. Lets say I wanted to run only the newly created tests so that the JUnit report is not skewed by the failures of pre-existing tests. Now this would help me in finding out if there was indeed a relationship between the quantum of unit tests newly written and the bugs per KLOC across previous releases and the current one. With a positive correlation (more tests --> less bugs from QA), you might think that one of the results of earlier sloppy code was getting fixed. You do not have to be an Einstein to figure out the 'why' part now - a happy set of developers (due to lesser bugs), a happier set of managers (more productive team due to lesser bugs and better code quality), And happiest me! (cuz I would have gotten the numbers to prove the claims from the dev side).

How do we identify all the newly added test classes? Enter SvnKit, the Java library that can talk to the SVN source control system. The SvnKit Wiki pages were quite helpful with their examples for me to quickly understand the API usage. Initially I ran into a problem when I tried using the custom "svn://" protocol to access the SVN repository. The error message that was being returned offered no help whatsoever in identifying the cause of the problem. It spewed pure gibberish as far as my grey cells could fathom. Thanks to my very knowledgeable colleague Ganeshji, the problem was quickly identified as a jar version problem. The SvnKit jars that I had used were old and could not work with the more recent SVN client that I had on my machine. With upgraded SvnKit version jars, I wrote a sort of SVN connector class, SVNConnector.java to ferret out the above 4 lists that I was interested in. The API provided a straight-forward way to access a file's latest revision details, which would also include the last modified time. So getting at the list of modified classes and tests was a cake-walk. The tricky part was in determining if the file was added during our iteration period (within a specified date range). Again the svnkit wiki came to my rescue. I got an idea from one of the samples that showed how to traverse the repository tree and that worked. The current hack I have am pretty sure is inefficient and slow. But for lack of ideas/expertise with the API, I settled for the hack to first get the job done.

The next step was to use the list of newly added tests from the SVNConnector and feed it to the ANT task that would execute the tests. Now to do that I had to make ANT talk to my list. That was not as straight-forward as I had initially imagined. I had planned to write my own ANT Task, but I figured out that I needed a specialized ANT FileSelector and not a custom ANT task itself. Wrote one and on the first run, as expected it broke. There was a problem in the way I was trying to pass in values to my custom FileSelector through separate nested param tag elements. That was incorrect, it had to be passed in as element's attributes instead.  Next I ran into a classpath problem. My SVNConnector class was not visible to ANT. I cursed scripting and its many followers. Finally figured out how to specify the path properly and then my connector was being executed via my custom FileSelector. But the first error free run was not ending at all and I had to kill the process. Wanted to debug and find out what was happening. To my utter dismay after a couple of hours of googling, I gave up trying to set up the debugger for debugging an ANT executed class. It seems to be due to ANT starting the program on a different VM and not the one in which eclipse was running. In my futile attempts I tried getting ANT to spawn a new jvm on a remote port that I could point my eclipse debugger to. Hard luck or I missed something. Nevertheless printing to console was the improvised debugging technology that I had to fall back on. Despite employing such impoverished resourceless-ness I finally managed to have the custom FileSelector work just as I wanted.
It has been a while since I had that satisfaction of creating something not done before. May be someone already has done something on this front before, if so Google has turned a blind eye to such information on the web and hopefully all you folks reading this will make the search engines take notice of this page.

The code (the connector and the ANT custom FileSelector) is here. No worries, no IP violation, no license, zilch.
Disclaimer : Use it at your own risk