Why Test?
All of the great programmers I know design their applications using Test Driven Development. Most of the other programmers I know have plenty of excuses why they don't (myself included). What's so great about Unit Testing and what are the benefits of TDD that make it so ubiquitous amongst the smartest programmers?
Firstly, unit testing. I find that if I don't write unit tests, as my application starts to get to a certain size, I lose trust in the code. In a complex end-client application I end up with areas of "don't go there" code which I don't want to touch as I know it works, but I'm not quite sure what would break if I change it. In my in-house framework and generation code I find that I have really cool automated code for speeding up tasks, but I often don't trust the corners and the edges of the automated code that I seldom use so if I run into a problem with them I just hack together a custom method rather than taking the time to make my core code more solid (as I'm usually on a deadline and it's almost always expressed in hours or minutes - not days or weeks). I'd really like to be able to build larger applications with confidence, but to do so I need to take the time to build it with components where I've worked through all of the corner and edge cases I can think of and have created an automated test suite so whenever I refactor my code I can see immediately whether it has broken any of the "contracts" that I depend upon in terms of my expected behavior for the code.
Unit tests can also be a great source of agile documentation. They are agile because they are very DRY - you are writing an executable test and just naming it appropriately to make clear the behavior that the test is checking for (and hence the behavior that your class supports assuming that the test is passing). There is no worry of the documentation getting out of synch with the code because if it does, the tests will stop passing and you'll have to rewrite them to express your new intent. And if you take a test driven approach to development, you'll have documentation of the intent of your new class files just before you code them.
Test Driven Development has some more subtle, but more profound benefits. With TDD, you write a test and then the simplest possible code to make that work - adding additional tests and the simplest code required to make those work until your tests cover all of the functions that your class files need to perform. After writing passing code for each test there is a "refactor" step where you clean up the implementation of the code (including the test code) to make it DRY'er and more maintainable hence the common "Red-Green-Refactor" description of TDD (write a failing test, write the simplest code required to pass the test, then refactor the code). It's important to realize that TDD isn't about testing. It is a different way of designing the details of an application. Not using TDD, I've noticed that it is often easy to write over complicated code or even to get stuck in "analysis paralysis" - trying to figure out how to write the one true API that will forever meet your applications needs! With TDD you work iteratively by adding a new requirement (a test) and then simply writing the simplest code that will pass that test. I'm looking forward to trying it on a real project as I've heard pretty much nothing but good things about the experience.
Stay tuned for more postings!



"All of the great programmers I know design their applications using Test Driven Development"...
Oh snap :) So it's like that?? .... just kidding.
I am looking forward to your exploration of this. Are you doing to stick to just CFC type testing, or are you going to be including interface TDD using something like Selenium? I can sort of wrap my head around the usefulness of CFC-TDD, but the idea of creating interface oriented test driven development is waaaay too crazy for me to wrap my head around. CFCs are so finite in their touching; on the other hand, the number of ways in which you can touch an interface seems infinite. And, if you have any sort of linked select boxes or AJAX style interfaces .... it hurts my head just to think about.
I am also curious to see if, like frameworks, there is a balance between usefulness and application size / team size. I know that no one plans for their apps to stay small forever, but I wonder at what point does this seem overkill.
Looking forward to your analysis.
The concept is quite easy. The practice can be difficult, because its hard to know what to test or how to test it when you start using it in practice. It gets easier with time.
Yep - there is always a balance. For a really simple app, I put the query a the top of the page and the display at the bottom - no OO required. I can create fairly simple OO apps without tests, but once I start having problems with edge cases or testing or am scared to change the code, I know that was a project I should have done test first. Its a no brainer for my framework, but the goal is to create a structure that makes test creation and running so easy I just do it for any class files I manually code. I'll be baking this into both LightBase and my deployment automation software so I can TDD everything that isn't just plain trivial.
1) Don't shoot for 100% test coverage. It's too damn hard to get there, and probably isn't worth it. Every "good" book I've read (or skimmed) so far on recommends 85%. which may be arbitrary, but I think the point is, 85 isn't 100.
2) Be very wary of downloading a unit test framework and generating tests for all your existing components. There's something really demoralizing when you do that, run them the first time, and see 500 failed tests.
Take baby steps. Get good momentum. Build good will between yourself and your tests. Don't shoot for the "be-all, end-all, I've tested every single corner of this entire component" test at first, i.e. swing for doubles, not homers. When i started writing tests, I did this, and it bit me in the butt a lot, because i'd end up writing really brittle tests that would pass one day but fail the next because they relied on external data or some such thing.
I'd also suggest this as a good start for building good will between yourself and your tests: try it out on an existing bug in a function that isn't 5000 lines long. you got a bug, write a testcase for it. try to write a single test function that proves the bug. then set to fixing it. even if the component under test has 20 other functions in it, try to fix just the one function that's busted. It's such a great feeling when you prove a bug is fixed by seeing the green bar!
Oh, and great preso at Boston from what I hear!
http://www.amazon.com/Working-Effectively-Legacy-R...