I've heard a lot of controversy among developers as to whether Test Driven Development (TDD) is really worth all the extra time it seems to take.
TDD means developing a small piece of functionality by first writing a test for it, then writing code to make that test pass. TDD should not be confused with BDD, or Behavior Driven Development, which is like TDD from a user's point of view, rather than a developer's. (Many people do BDD for the broad overview and then TDD for the nitty-gritty internal details).
So, for an example of TDD, let's apply it to making a job board. A piece of functionality might be "get a list of jobs with given text in the title." You might write a few tests like "with an empty database, create a job with the title 'Java Developer,' ask the Job class for all jobs with 'Java' in the title, and assert that I found that job." Then, do the same exercise looking for 'Ruby' and assert that you didn't find it.
But most developers will go a bit further than this and use a cycle of "red, green, and refactor":
- Red: write a test, to test whether the code (that you haven't written yet) does what you want... and verify that it fails. If it doesn't, then your test is meaningless! Writing good tests is an art unto itself.
- Green: make the test pass...and keep the whole test suite passing! If your code broke anything else, you must now go fix the breakage, whether that means updating an outdated test, tweaking your new code, tweaking old code, etc. You can't call it "green" until the whole test suite passes!
- Refactor: this is what makes it "go further."To refactor a piece of code means to improve the internal design or “clean it up,” without altering the behavior. If the way you got the test to pass was a horrible little kluge (admit it, we've all done it!), make it right before you check it in.
So... does this TDD process take extra time, and if so, is it worth it?
It's true, TDD will slow you down...but only in the very short term. If you just want to get a feature implemented today, and don't care about tomorrow, you might be better off skipping testing, whether before or after coding.
BUT…that approach is not wise in the long run. TDD is an investment, in the same spirit as avoiding "technical debt."
The best-kept secret of TDD is that it will help you get your feature or product to market even more quickly than skipping the tests, and with far better quality.
The process of getting a feature implemented and to market allows enough time for bugs to be noticed, and fixed. Because those bugs impact other features, which need to be fixed…and then other issues surface. You know the deal—situations crop up all the time that you just can’t anticipate.
That is where TDD will save your bacon!
The test suite you grow along the way will help get those features implemented, and bugs fixed, without breaking other features. It gives you guard rails. If something does break, the test suite will help pinpoint it, saving you hours of exploratory manual testing. In the long term it will save the project hours of exploration, debugging, finger-pointing, and other such nonsense... and, if you're really doing Test-DRIVEN Development, it will guide you to higher-quality code in the first place, saving months of disentangling and re-implementation.
But how does TDD do that? First, we have to define what we mean by "quality." The two main things TDD will help with are (#1 - from a general standpoint) it will make the app/product do what it's supposed to do, without bugs, and (#2 - from a geekier standpoint) it will ensure a better internal design.
The first part is obvious. After all, that's what the tests prove. But what about better internal design? What does that even mean? TDD forces you to think in terms of small, easily testable pieces of software design. This leads to code that is more reliable, modular, reusable, and flexible overall, plus a host of other benefits. For this reason, some people are now claiming that TDD should stand for Test Driven Design rather than Development.
If you include the Refactor part of the cycle, that's another investment that usually pays off in the long run. Paying attention to proper design early will make it much more likely that the code will stand the test of time, lasting much longer before needing to be totally chucked out and rewritten. We've all seen code so horrendous that we'd rather start over from scratch, rather than modify it—don't be "that coder!”
Bottom Line: TDD does make it take longer to implement a feature...but cuts the time to get it to market, and yields much better code, saving even more time and expense later.
Have you tried TDD? What’s been your experience?