TDD makes you deliver faster

I’m sick of hearing the same old song again and again: “we wanted to try TDD but it would make us go slower, and we wouldn’t make the business friendly deadlines so, you know, maybe next time”. This is bullshit. A myth. An urban legend. Not true. The truth is just the opposite: TDD makes you deliver faster. How can this be?

Well, it’s true that TDD makes you write more code than if you wouldn’t write automated tests at all. But, anyone who knows a little bit about programming will tell you that actual banging at the keyboard (i.e. writing or editing code) takes only a small fraction of programming time. Of course, this varies between developers and, of course, I didn’t measure it, but I’d estimate it to take only 10% to 50% of productive time (i.e. not counting the time developers spend surfing the net or attending the meetings).

All of the rest is consumed by various coding related tasks: thinking, designing, discussions, brainstorming, committing to the repo or updating from it, waiting for the code to build and/or compile (optional of course), digging through the docs, browsing help and forum sites.

And, if you’re not practicing TDD, you also have to waste a lot of time on debugging the application, manual testing (restarting it, logging in and navigating to the screen on which you can observe the effects of your changes to the code (again, optional), and fixing the regressions you introduced (not all though — only those that you noticed (and chose not to ignore) on your way to the above mentioned screen).

So, instead of wasting enormous amounts of time and effort on manual testing and debugging, the effects of which vanish into thin air with the next line of code you change, why not start writing automated tests and have these same tests executing over and over, automatically, for the project’s whole lifetime?

And one more thing about debugging: while working for 2,5 years with Ruby on Rails projects that have been done with TDD and/or had high level of test coverage, I hadn’t used a debugger. Not even once. Unbelievable for Java folks, but true.


8 responses to “TDD makes you deliver faster

  • a

    believable for java folks
    don’t generalize

  • szeryf

    Well, I wouldn’t believe it back then, when I was only doing Java :)

  • Evgeniy Dolzhenko

    No printf debugging in those 2 years either? :)

  • szeryf

    Well, of course, there was some printf-debugging (or rather p-debugging in Ruby), but I said “I hadn’t used a debugger”, not “I hadn’t debugged” :) If you have a comprehensive test suite, you can run some of them individually and nail the bug much faster.

  • I didn’t have enough time « require ‘brain’

    […] amounts of time (as opposed to writing quick & dirty code, which apparently takes no time). This is not true and I’m not the only one that thinks so. Of course, if you’re totally new to writing […]

  • Rick Pingry

    Hi Szeryf,

    Thanks for the thoughts. It is good to see there are some modern thoughts out there on this subject. 2 of us in our office have jumped into learning TDD for the past 6 months and we pair program as much as we can. We are working on an MFC based ActiveX control that talks to MS Office apps on the client machine.

    After 6 months, we still struggle with TDD a bit. We have had SOME good experiences, but we are still waiting for that “I’ll never go back” experience. It still feels a good bit slower to do the TDD. In some ways this might be due to needing to use C++, which requires the compile and link time, even if we are able to run our tests themselves in 4 seconds. The bigger issues, I think, revolve around the following issues… I would greatly appreciate any insights you might have. (Sorry this is so long, but I am REALLY interested in coming up with some answers).

    1. Doing TDD does NOT mean that we don’t manually test. I would never trust my automated tests so much that I don’t run every bit of code I write through at least a couple of use cases. There have been plenty of times that I have had all passing tests and something went wrong when I ran it, something I did not expect. I am working with some pretty wild external libraries (Microsoft Office Automation, MFC, and ActiveX). Which leads me to…

    2. Most of the time, I start off needing to do “exploratory programming”, I suppose that would be called a “spike”. Usually I need to do something manually with the 3rd party libraries to make sure it works, as mentioned above. I am not sure at first what needs to be written, much less what TESTS to write, so I take it one step at a time and investigate, building the code as I go. How do you do TDD with that? The expected answer is to throw the code away and start over. I just can’t bring myself to do that. I finished the feature, tested it manually to make sure it works, and even my “cowboy” code is not that bad as far as style goes. Throwing the code away just to add tests, or even add tests after the fact when I already know it works seems counter-productive.

    3. We have a hard time working out at what level we should be writing tests. Do we write tests around every class and function, mocking out all collaborators, or do we work at our own system boundary, mocking out the external interfaces? We struggle back and forth with this one. When we go to the class and function level, we have problems with the next two issues and we do not feel we are testing real issues from the users perspective. When we stay farther out, the tests are not as clear on testing one thing, have lots of duplication, and are larger and more difficult to write, but it is easy to see the use case and we feel confident that we are testing the integrations between our various classes and can easily cover refactoring.

    4. When testing every class and method, the required de-coupling to deal with TDD seems to make the code MORE complex than necessary. This may be due to needing to pass in collaborators for almost everything through dependency inversion so that we can mock out these collaborators. We have to make sure the collaborators are passed through the constructor using some kind of “Composer” class. Every code change seems to complicate the base.

    5. Going along with that, we have found that having test coverage, while it helps us to be confident that we are not adding defects, actually makes refactoring HARDER. Specifically, we are trying to work out the proper way to do an “Extract Class”. If you had class A with some functionality you extracted into class B, Do you move the tests that were already in-place into the tests for B then test A against a mock of B? Or do you leave the tests in place for A and make B an inner class? What if other clients want to use B? These kinds of things make it so we don’t want to refactor at all so as to not break our tests. Perhaps we are testing at the wrong level?

    Anyway, thanks again. I know that each of these issues might be an article, but I hope you have the time and inclination to tackle them. I believe there are a lot of us out here who are interested deeply in TDD. It makes sense on the surface, but in practice we struggle with it. After 6 months of working on it, the trite advice to “keep working on it and you will get better”, and “make your tests small and test one thing” seem pretty weak. I have read GOBS of books and articles on the subject, but they always seem to fall short on these issues. Please guide us.

    Thanks
    — Rick

  • szeryf

    Rick, thanks for raising these excellent questions. Here are my responses.

  • Rafael Ribeiro

    Good to see someone thinking the same :D.

    Lately on every source code I develop, i tend to implement it entirely using TDD (and i’m talking about real TDD, meaning writing the Tests before the code).

    I’m really grateful and happy with TDD, but i think it could get a lot easier.

    If we could make TDD easier to implement i’m sure more people would be implementing. I have some ideas, and it would be nice to discuss with you.

    Keep up TDDing :D.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: