views:

584

answers:

11

Duplicate:

For a developer that doesn't know about Test-Driven Development, what problem(s) will be solved by adopting TDD?

[EDIT] Let's assume that the developer already (ab)uses a unit testing framework.

A: 

Um, Higher code quality? Less bugs? Less wasted time?

Pick yours...

Yuval A
Why would you end up with higher quality code? Explain?
Andy Mikula
Because a test will reveal bugs before you deploy the code to production. You'll write "blue sky" tests that demonstrate proper usage and corner cases that might reveal weaknesses in your design. Your tests also act as documentation of the proper use of your class. AND your design improves because it forces you to think like a client of your class, because that's what the test is.
duffymo
Trollish question gets trollish answer.
Yuval A
agree @Yuvalthis question looks more like a way to get reputation than a real question
Edison Gustavo Muenz
And trollish answers get downvotes :)
Andy Mikula
It is a real question. Next week I'm supposed to convince a whole bunch of developers to start using TDD and I need good motivation. Besides, this is my first StackOverflow question. Thank you guys for all the answers so far.
Igor Soarez
Igor: Don't pay too much attention to down-voted answers. :)
Arafangion
+6  A: 

Presumably you test code that you've written before you commit it to a repository.

If that's not true you have other issues to deal with.

If it is true, you can look at writing tests using a framework as a way to automate those main routines or drivers that you currently write so you can run all of them automatically at the push of a button. You don't have to pore over output to decide if the test passed or failed; you embed the success or failure of the test in the code and get a thumbs up or down decision right away. Running all the tests at once reduces the chances of a "whack a mole" situation where you fix something in one class and break something else. All the tests have to pass.

Sounds good so far, yes?

The TDD folks just take it one step further by demanding that you write the test FIRST before you write the class. It fails, of course, because you haven't written the class. It's their way of guaranteeing that you write test classes.

If you're already using a test framework, getting good value out of the tests you write, and have meaningful code coverage up around 70%, then I think you're doing well. I'm not sure that TDD will give you much more value. It's up to you to decide whether or not you go that extra mile. Personally, I don't do it. I write tests after the class and refactor if I feel the need. Some people might find it helpful to write the test first knowing it'll fail, but I don't.

duffymo
so you say there's really no advantage in doing tests first? :(
Igor Soarez
Everytime I do the test first part of TDD I find that I do things faster. I just don't do that very often due to many many years of bad habits. It'll take me a while to cure myself of that I'm afraid. Net Net: It speeds up your development, increases the quality of your code and make refactors considerably safer.
Trey
The advantage of seeing the failing test first is that you know the test works. It has definitely happened to me that I was surprised when a test passed when it should have failed, proving that the test itself didn't work.
Yishai
I didn't say "no value" - I said I don't do it. That does not mean that others who say it's a good idea are wrong, I'm just relating my experience and half-arsed opinions.
duffymo
+1  A: 

Most of the people I have talked to don't use a complete TDD model. They usually find the best testing model that works for them. Find yours play with TDD and find where you are the most productive.

trent
+5  A: 

Ideally:

You won't waste time writing features you don't need. You'll have a comprehensive unit test suite to serve as a safety net for refactoring. You'll have executable examples of how your code is intended to be used. Your development flow will be smoother and faster; you'll spend less time in the debugger.

But most of all, your design will be better. Your code will be better factored - loosely coupled, highly cohesive - and better formed - smaller, better-named methods & classes.

Carl Manaster
+1  A: 

I made a big effort to learn TDD for Ruby on Rails development. It took several days before I really got into it and it. I was very skeptical but I made the effort because programmers I respect support it.

At this point I feel it was definitely worth the effort. There are several benefits which I'm sure others will be happy to list for you. To me the most important advantage is that it helps avoid that nightmare situation late in a project where something suddenly breaks for no apparent reason and then you're spending a day and a half with the debugger. It helps prevent your code base from deteriorating as you add more and more logic to it.

Ethan
+3  A: 

For my current project (which runs on a relatively heavyweight process), I have adopted a peculiar form of TDD that consists of writing skeleton test cases based on requirements documents and GUI mockups. I write dozens, sometimes hundreds of those before starting to implement anything (this runs totally against "pure" TDD which says you should write a few tests, then immediately start on a skeleton implementation).

I have found this to be an excellent way to review the requirements documents. I have to think about the behaviour described in them much more intensively than if I just were to read them . In consequence, I find many more inconsistencies and gaps in them which I would otherwise only have found during implementation. This way, I can ask for clarification earlier and have better requirements when I start implementing.

Then, during implementation, the tests are a way to measure how far I've yet to go. And they prevent me from forgetting anything (don't laugh, that's a real problem when you work on larger use cases).

And the moral is: even when your dev process doesn't really support TDD, it can still be done in a way, and improve quality and productivity.

Michael Borgwardt
In traditional TDD these are called acceptance tests, which are indeed expected to be written the way you do.
Yishai
+1 from me. I really like this answer, because it's a spin on the idea that I've never seen. Typical of the good stuff you post here regularly, Michael. Thanks for educating me.
duffymo
doesn't answer my question, but it's a very interesting point. Thanks
Igor Soarez
+8  A: 
wbyoung
+1  A: 

I personally do not use TDD, but one of the biggest pro's I can see with the methology is that customer satisfaction ensurance. Basically, the idea is that the steps of your development process are these:

1) Talk to customer about what the application is supposed to do, and how it is supposed to react to different situations.

2) Translate the outcome of 1) into Unit Tests, which each test one feature or scenario.

3) Write simple, "sloppy" code that (barely) passes the tests. When this is done, you have met your customer's expectations.

4) Refactor the code you wrote in 3) until you think you've done it in the most effective way possible.

When this is done you have hopefully produced high-quality code, that meets your customer's needs. If the customer now wants a new feature, you start the cycle over - discuss the feature, write a test that makes sure it works, write code that passes the test, refactor.

And as others have said, each time you run your tests you ensure that the old code still works, and that you can add new functionality without breaking old one.

Tomas Lycken
+2  A: 

(This is more of a comment agreeing with duffymo's answer than an answer of its own.)

duffymo answers:

The TDD folks just take it one step further by demanding that you write the test FIRST before you write the class. It fails, of course, because you haven't written the class. It's their way of guaranteeing that you write test classes.

I think it's actually to force coders to think about what their code is doing. Having to think about a test makes one consider what the code is supposed to do: what the pre-conditions and post-conditions are, which functions are primitive and which are composed of primitive functions, what the minimal necessary public interface is, and what's an implementation detail.

These are all things I routinely think about, so like you, "test first" doesn't add a whole lot, for me. And frankly (I know this is heresy in some circles) I like to "anchor" the core ideas of a class by sketching out the public interface first; that way I can look at it, mentally use it, and see if it's as clean as I thought it was. (A class or a library should be easy and intuitive for client programmers to use.)

In other words, I do what TDD tries to ensure happens by writing tests first, but like duffymo, I get there a different way.

And the real point of "test first" is get a coder to pause and think like a designer. It's silly to make a fetish of how the programmer enters that state; for those who don't do it naturally, "test first" serves as a ritual to get them there. For those who do, "test first" doesn't add much -- and an can get in the way of the programmer's habitual way of getting into that state.

Again, we want to look at results, not rituals. If a junior guy needs a ritual, a "stations of the cross" or a rosary* to "get in the groove", "test first" serves that purpose. If someone has their own way too get there, that's great too.

Note that I'm not saying that code shouldn't be tested. It should. It gives us a safety net, which in turn allows us to concentrate our attention on writing good code, even audacious code, because we know the net is there to catch errors.

All I am saying is that fetishistic insistence on "test first" confuses the method (one of many) with the goal, making the programmer think about what he's coding.

* To be ecumenical, I'll note that both Catholics and Muslims use rosaries. And again, it's a mechanical, muscle-memory way to put oneself into a certain frame of mind. It's a fetish (in the original sense of a magic object, not the "sexual fetish" meaning) or good-luck charm. So is saying "Om mani padme hum", or sitting zazen, or stroking a "lucky" rabbit's foot, (Not so lucky for the rabbit.) The philosopher Jerry Fodor, when thinking about hard problems, has a similar ritual: he repeats to himself, "C'mon, Jerry, you can do it!" (I tried that too, but since my name is not Jerry, it didn't work for me. ;) )

tpdi
+1 - "stations of the cross" - how very Catholic. 8) Deserves a point just for the phrase "audacious code". I love it.
duffymo
A: 

It is common knowledge that writing tests and having a large number of automated tests are a Good Thing.

However, without TDD, it often just becomes tedious. People write tests, and then leave it, and the tests do not get updated as they should, nor do new features get tested as often as they should either.

A big part of this is because the code has become a pain to test - TDD will influence your design so that it is much easier to test. Because you've used TDD, you have a good number of tests, which makes it much easier to find regressions whenever your code or requirements change, simplifying debugging drammatically, causing an appreciation of good TDD and encouraging more tests to be written when changes are needed - and we're back to the start of the cycle.

Arafangion
A: 

TDD (Test Driven Development/ Design) provides the following advantages

  • ensures you know the story card's acceptance criteria before you start
  • ensures that you know when to stop coding (i.e., when the acceptance criteria has been meet thus prevents gold platting)

As a result you end up with code that is

  1. testable
  2. clean design
  3. able to be refactored with confidence
  4. the minimal code necessary to satisfy the story card
  5. a living specification of how the code works
  6. able to support a sustainable pace of new features
Cam Wolff