As someone who's seen the benefits of the approach, I'm a huge believer in test driven development. It adds a level of quality and maturity to the field of software development, yet it's still not a widespread practice across development projects. When it comes to a choice between the features, time and quality, it's always the quality that suffers. We don't want to add extra time for testing and we don't want to compromise on the feature set of the delivery. If you haven't set out to do test driven development at the start of the phase, then it's difficult to fit in.
We've all heard excuses for not taking the test driven approach, but nowhere compiles them better than "Pragmatic Unit Testing in Java With JUnit", from the Pragmatic Bookshelf. I read the book a few years ago, and afterward I thought there was no way that any responsible developer could read the book without truly believing that unit tests were one of the most important aspects of the development activity.
The most worrying excuse I've heard is that it's too difficult to test my code. This can be for one of two reasons. One is that your code is mainly UI related, and automating the UI tests is too difficult. I'll concede that UI automation is a tricky area (but not impossible, as we'll see in a later article), but every effort should be made to automate it if possible: think about regression tests. If you have a fully automated test suite, including the UI behaviour, you can make a change to your code, and have full confidence that you haven't broken anything if you have tests to re-run.
The second reason that your code is too difficult to test is that you've messed up your design. Maybe your logic and UI code are too tightly coupled, and without that automated UI layer existing, the dependency between the logic and the UI will cause a problem. This is where test driven development helps to ensure a clean design, following best practices. Using JUnit is simple, so if I can just point my test at a clean logic layer, I can test all logic that the UI will ever touch. What's that? You're missing your data model? Well then just use mock objects - there are many frameworks for that!
For those who haven't read the book yet, I'll give a quick summary of the excuses for not testing as outlined in the introduction chapter:
- It takes too much time to write tests
As the number one reason that developers give, and thinking back on my own education, I think this is down to the way computer science is taught. For the most part, we're lead to believe that testing happens at the end of the process, not all the way through.
Pragmatic Unit Testing encourage the "pay as you go" model, where having tests written as you are developing means that you don't have that crunch time at the end where you try to cram all your unit tests in.
Anyway, if you're not writing tests as you go along, how are you checking if the code behaves as you expect? You run it manually? Wouldn't it make sense to invest some of that manual testing time into writing a JUnit test for it? I mean you'll have to run that piece of code again sometime - it's not going to remain untouched for the lifetime of the product.
In fact, there are many more time penalties that happen if you don't write unit tests. You'll have to spend time debugging code trying to work out why something doesn't work. Or you'll refactor the code, and then find that nothing works as it used to after the refactor. If you had the unit tests written, you have a base of confidence.
- It takes too long to run the tests
I'll admit, there can be a good amount of time taken running tests that involve external entities, or the user interface. But you're supposed to have more than one level of test. The unit level tests should run quickly, and there may be a level of integration tests that can run without a big time impact. If there are higher level integration tests that are taking time, just run them less frequently - maybe even in a nightly build. That's not to say you should ignore the lower level unit tests. These should always run fast enough that it becomes a natural part of your own development process.
- It's not my job to test code
I don't know at what stage a software developer decides that he can just throw code over the wall. If your job title was simple Coder than maybe there's an excuse. But as your job is to develop working software, you need to be able to say that your code is functional. The book makes a good point that if the QA development finds it difficult to find bugs in your code, it will do wonders for your reputation.
- I don't really know how the code is supposed to behave so I can't test it
This is a difficult one to react to without incredulity. If you don't know how the code is supposed to behave, you shouldn't have started writing it. You need to understand the requirements first.