When introducing a fellow software developer to the concept of unit testing you will very rarely be met with optimism. In fact, most developers will quickly point out that writing both the code and the unit tests will effectively double the amount of work that needs to be done and therefore increase timelines. This is especially the case if you’re working in an environment where looming deadlines are the norm, rather than the exception.
I was no different in this regard. When I was introduced to the concept of unit testing I did my research on the topic (read a few books, etc) and came to the conclusion that it would work in a few simple and isolated cases but that these were exactly the kind of circumstances were the overhead of writing unit tests would not necessarily merit the effort. I guess it’s natural for any developer to look at unit testing and immediately come to the conclusion that it would work for junior developers but for those of us who know what we’re doing it won’t really add any benefit.
How I changed my mind
I was lucky enough to be working with some clever and open-minded people at this time. At one stage I was busy struggling with a particularly tricky component and a fellow developer helped me write some unit tests. I wasn’t terribly keen on going through all this extra effort since I was confident that the code I had written was correct and my only real problem was figuring out what the business requirements were.
The first few tests we wrote simply confirmed what I thought already – the unit tests were simply slowing us down and not helping with my problem. And then… we found a bug. In my code. I couldn’t believe it – I had carefully thought out the algorithms and even manually tested the basic scenarios.
This completely changed my mind about unit testing. I immediately saw that the few simple tests we wrote would go a long way towards cutting down production issues and ultimately save us loads of time. I resolved to try and use unit tests in all the code that I wrote. However, I was still not doing TDD.
The next step – TDD
Again, I was lucky enough to be introduced to TDD at an early stage in my career. Unfortunately I just couldn’t get the hang of it. I tried writing the tests first, but due to the framework I was working with at the time this made my life very difficult and in the end slowed me down without improving my code.
It was only some time later that I really got the hang of TDD. I watched some webcasts and read loads of articles and I slowly saw the benefits. I was lucky enough to be working on MVC at this time (which is a very testable framework) and I completely switched to doing TDD in all my code. I haven’t looked back yet.
What I know now that I wish I knew back then
There are a couple of conclusions that I have made with regards to unit testing and TDD.
- It takes time to learn unit testing. I have seen many talented developers spend a few hours with unit testing and TDD and then completely disregard these concepts since they can’t seem to make it work. Unit testing and TDD are the same as any other concepts in software development – you need experience to make it work. You wouldn’t disregard MVC or NHibernate after working with these frameworks for a few hours, would you? The same goes for unit testing and TDD.
- Your design needs to be testable. You can have the best intentions in the world, but if your framework isn’t designed with testability in mind you’re going to struggle. This is why concepts like dependency injection and mocking are important. Again, this is something that comes with experience.
- There is nothing cooler than working with a fully-tested application. Once you get to the stage where you need to make changes to your application and you have 3000+ unit tests as your safety net, you’ll never go back. Make your change. Tests pass? Move on.
It’s natural for any skilled developer to miss the appeal of unit tests. We all pride ourselves in writing bug-free, efficient, perfect code. The truth is that we all make mistakes – not due to a lack of skill, but due to the inherent mismatch between business requirements and the code we write. Unit testing goes a long way towards solving this problem and I haven’t met a developer who, once they get unit testing, doesn’t embrace the concept.
What’s your excuse?