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 determinationWhen 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 valueOver 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 bulletAlthough 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 upIf 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.