• Anadi Misra

Introduction to Test Driven Development

How a simple practice of writing code after writing a failing unit test and writing only enough code to make it pass can go a long way in improving code quality


How I met TDD! 


I must admit that in hindsight I've also been the hit-and-trial programmer, in the sense that I'd never know how well (or otherwise) my code works until running it and doing some sort of automated unit testing or in some case manual testing on it. And more often than not my unit tests haven't help find out the defects that would invariably pop-up during testing. Quite naturally I was shocked when about a couple of months ago my project lead asked me, can you write a failing test for this first? My retard look at the point convinced him I had no clue what he's talking about so he dropped me a hint, look for TDD. And that's how it started.


A bit of Google search has revealed we have Mr. Kent Beck at the forefront of this idea. And there's some literature here and there from people who have been highly influenced by his way of doing things. Reading throught those initial articles was quite an experience of Aha! and Really! thrown in many a times. 


So here's how they explain TDD in one simple picture




And how exactly do we write a test for code doesn't exist? Well, I didn't find easy answers for that initally myself, until I came across this marvelous gentleman called Robert C. Martin, he actually makes a lot of sense in putting things through on how to go about it, and there are no more that three simple rules! 

  1. Write enough of test to fail, including compilation faliure

  2. Write enough of code to make that failing test pass

  3. Do not add any code unless it is to make a failing test pass


While as simple as it may seem, it takes quite some effort to get a hang of this thing in practice, there's also the much harder paradign shift ot deal with; for the life of me I still slip into my retard look figuring out a test when I haven't even written that code!

Let's look into a bit of snippets to understand what's happening here. And I'm going by the simpler examples available for this practice however, my intention is not so much on showing the technicalities as it is on what this could lead to if thoroughly practiced by an organisation (I've been told for example, the team that I'm working with, has had one production defect yes, only one in the last year and two months! That's some real performance and peer pressure for the new guy btw ;-)).


So if we were usually writing the code in the way we do here's some of the things that rarely cross our mind and even if they do, very few developers in my (limited) experience do go about actually acting on them

  1. Is this the least lines of code to get this done?

  2. Am I adding side effects to this object's behaviour?

  3. Does it really work? (ah! leave that to tester)


Now if I look at the TDD approach and what I've learnt of it. For example while writing a simple prime factor claculator (Haha! cheeky isn't it :-P) I'd actually fist write enough of unit test to make the most simple behavuoirs of a primefactor calculator, i.e. prime factors of 2, 3 are the numbers themselves, and then move to adding more conditions so my code would initally look like nothing more than 


public void testPrimeFactorFor2() { 
  PrimeFactorCalculator calc = new PrimeFactorCalculator();
  assertEquals(calc.getPrimeFactor(2), 2);
}

And my code 


class PrimeFactorCalculator { 
  public int getPrimeFactor(int number){ 
    return number;
  }
}

Yes while it does the job of finding prime factor for 2, the code is far from complete. I would then add antoher test to see what does it return for prime factor of 3


public void testPrimeFactorFor3() {
  PrimeFactorCalculator calc = new PrimeFactorCalculator();
  assertEquals(calc.getPrimeFactor(3), 3);
}

And of course this would fail and I would have to write the code to make "just these both tests pass"; while this might look futile for a prime factor calculator here's the larger picture to which I want to draw attention, notice how we are writing just enough code os coming back to my thoughts of steps which are always an afterthought and require effort hence mostly neglected


Is this the least lines of code to get this done?


yes we can be very sure about that as soon as this test passes;


Am I adding side effects to this object's behaviour?


Since we concentrate on writing just enough tests to for a non present behaviour and just enough code to make them pass; we can be sure of no side effects; again as soon as tests pass;


Nothing much to say here other than; if the test passes, don't worry about it (you have to write the right test though; and I agree that doesn't come easy; but worth practicing to get there)


The other advantage is that you are able to iterate through your object's design one step at a time thereby ensuring you've broken down the entire logic into very simple objective steps to be accomplished independently, thereby eliminating both over and under engineered code. What's also remarkable to see is (IMHO) we are building a thorough layer of thorough automated regression which should help our rhythm in the rather small and high pace iterations of Scrum.

I'm by no means very well acquainted with this proactice, but the couple of months that I've been doing it has proved a very interesting experience, and given what I hear from my (super human) team looks like it works very well indeed!

 

Bangalore, Karnataka, India.

  • Facebook
  • Twitter

©2020 by Anadi Misra.