Posterous theme by Cory Watilo

Deliver better software by mastering test driven development

My path to mastering TDD (test driven development) has been rocky, it's the technique that I now adhere to. A recent tweet from Ben Rady hit the nail on the head:

Test Driven Development is the "rock hard abs" of programming. Everybody wants it. Nobody wants to do the work to get it.

I was introduced to TDD when I started working with Ruby on Rails. It seemed to be a movement gathering interest in various communities. Back then I thought testing was something that only happened after programming, perhaps by independent testers who would provide test reports based on the criteria. You'd start with requirements analysis and construct test plans, test case documents etc, but running tests to deliberately fail before you code anything was alien to me, and something not taught during my degree. Initially I remember questioning its value, it seemed to get in the way and hold me back. Running the tests was a pain and everything seemed to take twice as long to code.

Patience and determination

When learning new programming concepts, languages etc it's easy to get caught out and to become frustrated. When problems remain difficult to solve I've often found it's due to an incorrect approach. Although when starting out with limited knowledge it can be difficult to realise it. This leaves you in the predicament of learning more which takes valuable time or giving up and moving on.

Giving up is all too easy when it comes to testing. In the past I gave up with excuses such as time constraints. I've worked on a few projects with small or near empty test suites which initially seems OK, but after a few months those thoughts turn to worry and uncertainty especially when the code base starts to show its rigidity and brittleness.

Starting out my non test driven mind always kicked in, I was thinking I can just code it, test it quickly in the browser and move on. You have to fight those thoughts, reason with yourself, rationalise and logically think about the benefits the time upfront provides.

I think it requires a mind shift to become a developer who uses TDD/BDD instinctively. You have to learn to think differently and that takes time, I can't imagine any less than 6 months depending on your will power. Never give up though, if you are en route and want to get there you will. From experience I'd say it's helpful if you start small and don't try to take on everything at once, it can be overwhelming. As soon as you are comfortable in one area you can look at leveling up. If you have the option of working with someone who is already ahead of you then this should accelerate things too.

My step by step approach

I started with unit tests. Once comfortable I started with simple functional testing, again more time passed and I felt confident enough to look at full stack integration tests. For the past year or so I've been learning to spin that around and start at the behavior level and drill down exposing the required functionality. This path isn't what I'm advocating, it just been my path. In hindsight I wish I had moved on between steps faster or even took a different approach altogether. Now there are many books and online resources that teach you a how to write code in the language of your choice with a full BDD/TDD approach from the off. You need to experiment to find what works for you.

Tests will prove their value

Over the years I have been burnt by untested code. Every time it happened it just reinforced my belief in writing tests. It's been a reoccurring lesson, I didn't test upfront and something fails, often as a result of a change. The root cause can be difficult and time consuming to track down, if it hasn't been brought to your attention (or some unfortunate user's) early enough a raft of further changes may have been committed since it was introduced.

A good test suite not only provides confidence as you make changes but also when you want to rip out a feature, refactor, upgrade libraries or add functionality. You'll thank your test suite when an automated test runner notifies you that you've just broken something. Now on the other hand if there is no test coverage it's a very different story, you have to tip toe around hoping your changes are OK, then you end up having to test as much as you can in the browser and whatever tools you have; basically time wasting with non repeatable manual testing.

No silver bullet

Although testing offers numerous pros remember there is no silver bullet! You start out by spec'ing functionality and building on it as you discover more permutations. Even so, unexpected errors will occur. At least when you have your tests in place you can add a regression test. Once you make this pass you have the bugfix which you know works with existing functionality. I recently read somewhere that if you ever see an error in the browser stop immediately and write a failing test for it, sound advice.

Wrapping up

If I had to plot the learning curve for testing I'd say it would look a more like a stair case. You'll be working though and suddenly you'll hit a wall. Overcoming the wall is often difficult and I think this is where people drop out using the unsolved problem as a scapegoat. Time is often another reason people give up. You simply have to accept that learning anything can take time and learning to write tests is no different. The tests will increase the chance of finding problems sooner in the development process, when they are cheapest and easiest to fix saving you time and money in the long run; pair-programming also aims to offer the same benefit. Once you start to become comfortable with how to test effectively you write the tests faster meaning you're spending even less time upfront for the same return.

If you don't already write tests consider trying it, take a look at the tools available to you. If you want to test but don't for some reason or another, try to identify what is stopping you and look for ways around it. If you already write tests is there an area that you're not strong in or ignoring, can you level up?

I've persevered with TDD and believe without question that it's helping deliver better quality code that's less brittle to change, which is exactly how software should be.

Refinery CMS: Consider it if you are searching for a Ruby on Rails CMS

Refinery CMS is something we've recently stumbled across at work. I'm going to explain why we have taken to it like a duck to water.

In the main we build web applications, not websites. The problem is occasionally the former requires the latter. Using Ruby on Rails I have been able to work on a vast array of different, interesting, simple, complex you name it web applications; but there has always been this niggle that the CMS part is missing. There are lots of Rails CMS alternatives out there but we've never really been hooked by one for some reason or another. Rails being Rails means with a little time, custom CMS functionality has been -chucked- built into some projects, everyone knows you can write a blog in 15 minutes with rails, right!?

The problem with that approach is the re-invention of the wheel, plus that blog or pages engine written in 15 minutes doesn't touch that stable, fully tested feature rich one a team of programmers have been working on for years.

What I love about Refinery CMS is that it's really geared towards the end user, i.e. to add content like pages, news articles, images etc the client doesn't need to be a programmer and certainly doesn't need to learn any template language. For them the WYSIWYG editor is simple and offers plenty of power. Don't get me wrong, you will need a developer to get everything up and running, unless your client is very technical minded. Once setup though it's extremely easy for the user to take over. Depending on the client's ability, understanding and your trust you can offer a fair bit of control over to what they can do, such as deleting that core page contact us or messing around with other settings.

As much as I love the end user I'll be honest, how difficult my life becomes is pretty important too, after all time is money. This is where Refinery CMS wins hands down for me. In principle it's just rails app. In fact it's just a rails app with many engines as its core. The beauty of this is that you can do whatever you like to it with ease. The architecture allows you to add your own functionality in the root of the application or through additional plugins. There is even a simple plugin generator to make adding new ones a breeze.

Since working in Rails I've always wanted to get involved with an open source project but have honestly been a little worried I wouldn't have much to offer. Refinery has helped me get over that fear, quite quickly in fact. The core team are very helpful but do rightfully ensure the project upholds their vision.

It's not yet at its first release so things are changing and improving all the time, but it's not hard to follow and upgrade. Tests are being added all the time which will improve the stability in the long run. The plugin list is growing, we've added our own, a simple way for handling testimonials, we're also working on one for vacancies. Looking at the github network you can see others are helping with i18n and bringing it all up to rails 3.

Refinery continues to help us tackle some of our projects, it's also improved my knowledge and finally got me contributing back to open source. If you're looking for a Ruby on Rails based CMS, I would highly recommend you check it out!

The smartest, ideal, efficient programming can still look awful!

I always try my best to write extremely neat code; even if I fail. I'm a complete stickler for it. I think it's because as a programmer one of things that frustrates me most is looking at messy code. Before I can even begin to start solving or understanding the logic involved I often spend time sorting out the indention. Whilst doing that I'm usually thinking this should already be done, not many clients are particularly willing to pay for time spent on this. The idea of re-factoring bad code is a difficult sell; we've found explaining the long time benefits and future time saving can help.

I think my C programming tutor back at uni grilled it into me, that the code just has to be neat and well organised, even if it doesn't work initially. Thinking back it was probably just to make her life easier, seeing as she had to review it all. But hey the result it's had on me is hopefully a good thing, helpful to me and others who look at my code.

Building Rails applications daily does tend to help with many conventions; most of the code I pick up has that going for it, although staying DRY, useful comments, good documentation, sensible variable names and consistent indentation especially are often slightly lacking.

Everybody is probably guilty of thinking I'll just get this working first, then I'll organise it afterwards. The problem I've found with that approach is it very rarely gets sorted, leaving your perfect solution looking a little wilted, confusing and quite simply messy.  If like me you feel you could improve and would like to perfect the readability of your own code, I suggest you checkout the Top 15+ Best Practices for Writing Super Readable Code article posted this morning. It's a great tutorial; just imagine the hours we could save ourselves in the long run….