One of the arguments that I see a lot in favor of Test Driven Development is that it helps deliver higher quality software more quickly. The more I projects I take part in or observe, I realize that this is only half true, and less than half true for Agile projects. I’m not saying that TDD has no place in Agile projects, just that it has a very specific place and time.

What is a unit test really?

A unit test is a risk reduction strategy.  You are adding code to reduce the chances that there are bugs in the code that you’re testing. Managing risk is an essential part of managing any project, there are other risks that need to be weighed and considered, like the risk of missing deadlines. These need to be balanced against the protection that the unit tests provide.

YAGNI

Ya Ain’t Gonna Need It, the mantra that infuses most Agile projects boils down to don’t make things that don’t add value for the customer. Let me ask you this question, “How many customers have asked for unit tests as part of their project?”

For me, in 20 years of software development, the answer is 3. In all three of those cases, the project was to deliver a library, where the unit tests were essentially tutorials in how to use the library. The remainder of the time, I don’t think a customer has cared that unit tests exist, much less about the code coverage of the unit test.

I have been to a couple of sprint presentations where people have demonstrated working software with unit tests. Even with a product owner that is reasonably technical, demonstrating that the unit tests work tends to be greeted with a “ho hum” reaction, sometimes it comes down to a very uncomfortable question of “So what actual working business application are you going to demonstrate?”

It’s hard to make the case that the unit tests are directly on the critical path for delivery of the product. If you’re following a more lean approach, that makes unit tests waste, something to be avoided.

Drag

In fluid dynamicsdrag (sometimes called air resistance or fluid resistance) refers to forces which act on a solid object in the direction of the relative fluid flow velocity.[1][2][3][4] Unlike other resistive forces, such as dry friction, which is nearly independent of velocity, drag forces depend on velocity.[5] 

from http://en.wikipedia.org/wiki/Drag_(physics)

This applies to software development too. The faster your velocity, the more effort must be put into maintaining all the things that add drag to a project, updating the project tracking tools, presenting to business owners, or maintaining unit tests.

For example, say you have a project that has good separation of concerns. you have a UI layer, a business object layer and a persistence layer. You have been following good TDD principles where each layer has tests that are independent and rely on mock objects to provide information for the tests. It all sounds great. Now imagine that you need to add a new field to the UI layer that’s stored in the persistence layer. So you have to update the UI layer, the business object layer and the persistence layer. Also you have to update the tests for the UI layer, business layer and persistence layer. Oh yeah, and you need to update the mock objects for the persistence layer and the business layer. So to add a field to the UI, you need to update eight things, three real objects, three unit tests, and two mock objects.

That’s drag! Updating eight objects when you only really need to update three. Regardless of how fast you type, that has a delaying force on you. It slows you down. Unfortunately, when people are confronted with drag, the natural inclination is to reduce it, usually by not updating the tests, which drive code coverage of the tests down reducing the value of doing TDD at all.

 Intelligent unit tests

The best time for unit tests is when dealing with bugs that testing, or customers, have found. That’s when it makes sense to construct a test that exercises the bug.  that way reproducing the problem is simple and can be done as often as you need.  Those tests provide value, you can use them to say “This problem that you showed me is fixed, and can’t recur again.”

Conclusion

Each test adds it’s own increment of drag to the process. So tests should be used at the right time and for the right reasons. Ideally, that reason should be that it adds business value for the customer, but regression insurance is a good reason too.

Advertisements