Sunday 27 September 2009

What are people saying about TDD?

Here are some of the positive things that people are saying about Test Driven Development.

Said by potatoihave on Twitter.

Huge payback today as I made big changes to a library, and my tests saved me from surprise after surprise.


Said by panesofglass on Twitter.

I think I'm finally really getting #tdd, and I can't imagine how people want to war against it. It makes coding so flipping easy.


Said by runegri on Twitter.
TDD is so incredibly nice! I just did a major refactoring of my pet project and I know for certain that I didn't break anything


Said by oliyoung on Twitter.
I really don't know how you do anything like a decent webapp without TDD and a good CI framework these days

Saturday 26 September 2009

TDD Shoots Cowboy off His Speedy Horse

There is a cowboy developer\programmer, speeding through the wilderness on his horse. He can produce code faster than anyone.

Give him a rough sparse user specification and he will have a working solution in a matter a days.

So, if you were to enforce TDD on this cowboy, of course he will say that it slows him down. It will slow him down significantly.

He has never done any design in the past, now you are asking him to design his whole application.

It’ like taking him off his horse and removing his Stetson. You are trying to change him from a cowboy and on the way to being a professional. Do not expect that to be easy.

Of course he will fight against it. He can produce an application in a month, whilst the same application written with TDD will take 6, 7, or eight weeks, certainly a longer period than the cowboy takes.

Do not get me wrong when I say the cowboy can write an application in one month. It’s is usually an illusion. The customer will like the look of it. The customer may even test a few of the features and say WOW. What the customer does not know, that underneath that pretty UI is a pit of snakes and scorpions just waiting to bite.

Customer: Can we have a feature added?
TDD: No problem, should be ready in two days and I can prove that I have not introduced any bugs.
Cowboy: Dunno about that. The coding is fixed. You’ll have to be responsible for any bugs that are introduced. You really should not be introducing changes at this late stage

Manager: We’ve got a new Developer joining the team. Can you get him up to speed on the project?
TDD: Yes, the Tests serve as a ‘living’ fully up to date design document. The new Developer can quickly see the purpose of classes and methods. The new Developer will become productive in just a few hours.
Cowboy: I can’t really show someone how my code. (Secretly I do not know how it works myself. I’d be embarrassed to show the code to someone else.) We don’t need a new Developer. I can finish off. Just give me pizza and let me work through the night and weekends.

Team Leader: Change the algorithm in a method to make it more efficient.
TDD: Not a problem. This is called re-factoring. We do it all the time during TDD.
Cowboy: Change one of my methods? Do you realise that it will have an impact on the rest of the application? This could set the project back by weeks.

Oasis, thanks for your comment on 27 Sept 2009

I just want clarify what I mean by refactoring.

Suppose we have the following method.
        public Price GetPrice1(List prices, string requiredItem)
{
Price priceFound = null;
foreach (Price price in prices)
{
if (price.Name == requiredItem)
{
priceFound = price;
break;
}
}
return priceFound;
}

The code can be refactored in the following way.

First, the method signature must NOT be altered.

The code within the method can then be improved. For example a decision may have been taken to implement LINQ for objects.

All the tests should still pass and have no knowledge of the fact that the method has been changed.

      public Price GetPrice(List prices, string requiredItem)
{
return (from n in prices where n.Name == requiredItem select n).SingleOrDefault();
}

Saturday 19 September 2009

I Enjoy TDD because ...

I’d like to know why you enjoy using Test Driven Development (TDD).

Just leave a short message about why you love TDD, how did you get converted?

TDD We got no time for that.

I have been on two projects where the Developers were instructed not to use TDD, because, “We don’t have time for that.”

In my head I am saying to that person, “What! You don’t have time to let me design the software that you so urgently need?”

I am not sure why corporate companies get into this state. Perhaps a few executives pick a random budget, say £2,000,000.

The processes in the corporate environment then burn up a lot of that budget. Constant meetings, planning, prioritisation, risk management, highly detailed design documents etc.

When it gets down to doing the actual coding, there is only 5% £100,000 of the budget remaining.

Of course there will then be panic. Of course a Project Manager is not going to be impressed when you say you want to increase the code production time by using TDD.


It’s kind of ironic, that the rushed coding, hacking, panic, misunderstandings lead to more bugs which would have been detected with TDD.


It really is sad when a project finds itself I this state.


Yes, at the Development stage TDD obviously takes longer.


But you’ve got to look at the bigger picture.


  • Better quality code delivered.
  • Code that is more stable.
  • Code that is far more easy to maintain.
  • Code that can easily be enhanced with new features.
  • Far lest bug bounce between Customers, Testers and Developers.
  • Oh and a far calmer, professional working environment.

TDD Travels Back In Time

Fixing Bugs in Legacy Code

Sometimes we have to fix a bug in code that was not developed using TDD and has no tests.

What I do this is to use one of the main principles of TDD and start with a failing test.

This failing test should replicate the bug report.

Then when you fix the code, the test should pass.

Sometimes when looking at an ‘old’ piece of code in can be tempting just to try and fix it.

But make the effort of adding a testing framework and the first test. You and your colleagues will benefit in the long run.

The code will gradually become more stable and more maintainable.

This principle can also be used when adding new functionality to an existing application that was developed without TDD.

TDD Spawns a Guardian Angel

OK We all know that TDD is a technique for DESIGNING your code.

One of the massive side effects of TDD is that you end up with a set of tests that should give nearly 100% coverage of your code.

This set of tests is what I refer to as your Guardian Angel. The effects of having this set of tests constantly looking over your shoulder is immense. Especially if a project reaches a panic stage where people are introducing late changes and new requirements. Being able to run hundreds of tests before doing a build and release is immeasurable.

The set of tests can also come to your rescue when someone says have “you got any design documentation”. Of course you have. The tests represent the most up to date design document that you can have. (Unlike separate documentation that can quickly become out of date.

So, have you got a Guardian Angel or a little devil on your shoulder?

Friday 18 September 2009

TDD is a complete failure.


What I mean by that is when you design a method using TDD, you start with a failing test, and you then implement code to make the test pass.


The test defines your expectations of the code that you will be designing. When writing the test, think in terms of what a client or consumer would expect of the method.

Let me demonstrate. Imagine some sort of financial accounting system. We have a list of credits, money going into the account and a list of debits, money leaving the account.

For the sake of this demonstration, let's have the two sets of values in two arrays:

int[] credits = {23, 42, 117, 11, 48};
int[] debits = {93, 22, 38, 29, 14};

Our first test will look like this. (This is written in C#)
[TestMethod]
public void Calculate_CreditsGreaterThanDebits()
{
int[] credits = {23, 42, 117, 11, 48}; // Total: 241
int[] debits = {93, 22, 38, 29, 14}; // Total: 196
Account account = new Account();
int balance = account.Calculate(credits, debits);

// We expect the result to be 45, that’s (241 - 196)
// In TDD we can perform various checks using something called an assert.
// In this case, I just want to check that the balance is equal to 45.

Assert.AreEqual(45, balance);

// If the balance is anything other than 45, the test will fail.
}
First of all our code won't compile, so add the new method Calculate with the minimum of code to enable compilation.
public class Account
{
public int Calculate(int[] credits, int[]javascript:void(0) debits)
{
return 0;
}
}

The project will now compile. Run the test and we will get the following failure.

Assert.AreEqual failed. Expected:<45>. Actual:<0>.

That's good news. In TDD we love a failing test. We can now do the enjoyable part of writing real code to make the test pass.

public class Account
{
public int Calculate(int[] credits, int[] debits)
{
int totalCredit = 0;
int totalDebit = 0;

foreach (int credit in credits)
totalCredit += credit;

foreach (int debit in debits)
totalDebit += debit;

return totalCredit - totalDebit;
}
}
Run the test again and it now passes

Notice the name of the test, Calculate_CreditsGreaterThanDebits.

The first part, Calculate, indicates the target method that I am designing. The second part describes the scenario that I am designing for.

The name of the class that contains this test is AccountTests. This naming convention means that this test class will be used to design the methods in the Accounts class.

Having got this one scenario working, you then implement a few more scenarios such as:

Calculate_CreditsLessThanDebits()
Calculate_CreditsEqualToDebits()