Wednesday 23 October 2013

Unit Testing / TDD - initial rhetoric

I was talking to a mate/colleague the other day @ CFCamp, and the topic of unit tests came around, and that they... well... didn't do any. They were aware this was not good, but had a sorta mental block of how to get going with TDD and the whole idea of test-first code-second. I had to admit I only started doing unit testing in my current role, and I have our lead architect, Simon Baynes to thank for this. For the preceding decade or so of my development career my approach to testing was the standard cowboy approach of if something didn't seem to break it was probably OK. A lot of people take this approach. It's a shit approach. Don't do it.

In my own defence (it's a lame defence, I hasten to add), I can explain away my lack of unit testing practice for the first few years of my career as I was one of these typical CFML developers who wasn't aware of the wider industry around me, so having not thought to investigate stuff like good coding practices and to check how other people did stuff. Also when new to dev I was in a very jack-the-lad cowboy-ish environment in which doing a decent job of anything was shunned in favour of doing the quickest job possible. Not ideal.

However ignorance is not a defence, and certainly for a few years after my start I was well aware of unit testing as a concept, but never really looked into it. I was like "yeah, I know I should look at this stuff, but it'll just end up meaning I have to write a whole lot of boring test code, and who wants to do that?" This is a very immature, lacking-in-self-disciple attitude, which I now regret.

To be very clear, I'm now of the position that if you are not doing TDD, then you're not really conducting yourself in a professional manner. It's as simple as that. Unit testing your code is as intrinsic to your work as source-controlling it. And you're also not doing yourself any favours because if you do do TDD, your code will just be better, more stable, and less likely to need revisiting down the track. But if you do need to revisit previously written code, the job is a lot easier because your confidence that changes you make don't break existing code is going to be increased due to already having test coverage for it.

It adds a bit of overhead at the beginning, but it improves your code design, clarifies what code you need to write, and cements expectations. It also helps to minimise unnecessary code because any code you write needs a test, so one ends up being more circumspect with one's planning. I think the net difference in code development / maintenance time would not ultimately be negatively impacted by adopting a TDD approach: slightly more cost at the beginning is met by less subsequent maintenance overhead. That said, this is just an instinct, and I have not done any actual metrics on it.

I'm quite pleased that in our core API at work we have about 35000 lines of code, and over 60000 lines of test code. And this equates to almost 3000 tests. That said: we don't have 100% coverage - and not all our tests are the most excellent work ever - but it's strong in areas where it counts, and we are continually improving coverage and indeed improving the tests as time passes (we're learned a lot in the course of writing these 3000 tests, and our approach has been fine-tuned).

Why am I telling you all this? Well because I'm gonna write a few articles walking through some stuff relating to unit testing, and I figured I should explain why first. That was gonna be a para at the top of the first article, but actually this is now almost long enough to be an article in its own right, so I'm gonna proofread and press "publish". For your part... do you do unit testing? If not, why not? And it's a genuine question. I think people can learn from reading other people's experiences.