Wednesday, August 1, 2012

Test-Driven Development: By Example

One of the books in the 8th Light apprenticeship book series is, Test-Driven Development By Example, by Kent Beck. The book takes a deep look at testing, what it means to not only write tests first, but to continuously drive your development from them. Beyond the ideals, examples and general share of knowledge on the subject, Kent provides some great explanations of practices one can employ to be a better TDD developer and have less stress while following the process.

What was TDD to me?

From when I started testing to where it has evolved; I looked at TDD as a way to enforce the individual parts of my design were confirmed to be working before I put them together. Once I had the design planned out, I would put into place as many tests as I could think of for the initial phase of development, and then begin to build them out until eventually I had all the tests passing and a bunch of new ones added during the process.

In the end, I would have a pretty well tested system, and a confidence as strong as the care I put into the tests.

What is TDD to me now?

Since I began talking with the various people at 8th Light, I quickly realized that I was missing a very important part of TDD, driving my development from the tests. As I got further into Kent's book, it became pretty apparent just how important this step was. With the testing mantra, Red, Green, Refactor; You create a test, write the absolute minimum amount of code that will make it pass (even if its not the right code), then refactor all of your code to clean it up and reduce duplication.

Although I had lost my fear of refactoring a little while back, it had been nothing more to me than going back days or weeks later to clean up what I was rushed through to finish. With minimal code and refactoring immediately takes development in a completely different direction, literally you will have the minimal amount of code needed to have a working system. The confidence level of your code will be at its highest as you will have tested and refactored your code thousands of times catching bugs instantly.

As I am breaking down my Test-First Development and turning it into Test-Driven Development, I find myself fighting how I think a system should look and finding the next best test to prove it. To really take a deeper look at where I'm at in the current design and what the end product needs next to become one step closer to being completed. Right now, it feels like less code is just a happy side-effect.

Test Helpers

Beyond the examples and general testing knowledge in the book, two of the chapters really stood out to me, Green Bar Patters and Refactoring. Maybe its because I have a little bit of testing background maybe those chapters really are more important. At any rate, they really provide a great deal of understanding on how to develop via TDD pretty well.

Green Bar Patterns

In the Green Bar Patterns, Kent really digs into how three very practical ways to write effective tests. First by faking the code that a test wraps you get a quick successful green test and literally the absolute code needed. If your method under test has a test that says the result needs to be '5', then have the method return '5'. Technically speaking, that's all your code needs to do. No addition, no subtraction, no calling out to other classes, just the result. Then as you write more tests or triangulate your tests the requirements change and you continue to fake as much as you can or write as little as you can to make them all pass. Eventually the design will have been created.

When you are writing your tests if you don't feel up for faking the implementation or you need to drive the design more in one step, you can triangulate your test. By creating two assertions in your test that would get the same result but not through faking it, you have created the two points needed to find the third. The third being the implementation.

In the same manner as triangulation helps to drive the development faster with less tests, another practice furthers this and is called Obvious Implementation. Which is simply, if you see a simple solution to the test you have created, go ahead and implement it. This further saves time and energy to keep going. Then as you are developing, depending on the complexity or understanding of the problem at hand, you can vary which practice you are using to help you complete it.

Refactoring

For me, refactoring has always been an important part of the process. My willingness to hop into a portion of code I haven't been in for a while and just start changing things with out fear of breaking something somewhere else came when I started understanding testing better. As such, I found that my refactoring skills developed later in the game than the others. This chapter of the book really goes through different practices of refactoring and details the whys and hows. This one is definitely one of those sections of a book that needs to be revisited from time to time, pulling in more as your understanding changes.