That's mostly a beginners problem, I know several people where it's mostly:
1. Write a lot of code
2. Test it
3. It works!
4. Test it
5. It works!
6. Test it
7. It works!
...
15. Test it
16. It works!
17. Are you done?
TDD in no way makes 17 any clear, because every test they thought of before writing the code works more or less the first time. And that's the core problem with testing, for a solid developer what fails is has nothing to do with the code it's always a question of edge cases they did not think. (Wait, some sales people are their own managers and outside consultants at the same time? well just bob) You can force these people to write tests, but it really does just slow them down.
Not groking TDD, I literally worked my way thru the book, doing each and every step, just to get the gist of the experience.
TDD works fucking great. If you know what you're doing.
Alas, that's a big IF. Most of the stuff I do, I'm just figuring shit out.
Mostly, like when designing a new library, I work outside-in. I imagine how I'd want to do something, writing the client pseudocodeish stuff first, and then trying to make the implementation support my idealized programming mental model.
I end up throwing away A LOT of code. Getting something short and sweet takes a lot of experimentation, most of which are duds.
Though my personal approach of outside-in is trivially like TDD, it's not nearly as rigorous. Were I to be as thorough as TDD, I'd be spending all my time writing tests. Which seems pointless, for code I'm like just going to throw away.
Anyway. Much respect for the guy who wrote that first TDD book. It's one of the few methodological strategies that works as advertised.
I do strict TDD when I can, and I consider spiking out things part of the process. If I need to approach a problem that I don't know how I'd solve just yet, I create some sample code I later trash and do a lot of work in the Ruby console.
Then, once I've gotten an idea of the problem, I can start writing out some pending tests that help me figure out structure, and then I'll start into the strict TDD loop of write a bit of test, watch it fail, make it pass, write more test, etc.
It's not about telling you when you're done a feature. It's about leaving step 17 with a set of tests so that the next person in the code can tell when he's done without doing steps 1-17. And you'd think it slows you down, but it really doesn't. Some advantages of TDD are less context switching (you can test your code without even leaving the code itself) and a high degree of focus (every atomic subtask has a very clear completion criterion: fix the failing test). Those are things solid developers love.
I have never seen any half way decent developer write code for more then a few minutes without some sort of feedback, automated test suite or not. You are right that it will work more or less, but they work out the "less" part of that statement sooner rather then later. In my experience, that is a place you get to over time, only the people out of college write code for multiple hours straight, then debug everything afterwards.
That is actually the primary goal of tdd, to free you from the more mundane aspects of the code/run/debug loop. The secondary goal is to give you a good base for changing the code later and finding out what broke, again without a ton of manual actions. But as useful as that is (and it is extremely useful), it doesn't hold a candle to the first benefit.
> I have never seen any half way decent developer write code for more then a few minutes without some sort of feedback, automated test suite or not
I do this all the time. Two reasons:
1. I can keep in "the flow" for an extended period of time. This is more important if the code is especially complicated. If I have to stop every few minutes to fix trivial errors, it's easy to forget important details of how everything is supposed to work.
2. Not having any feedback forces you reason about the code before writing it. It's very easy to fall into the trap of writing code, then waiting until it is tested to find the errors. Thinking before writing is the fundamental skill that TDD encourages, but you don't need TDD in order to do it.
> only the people out of college write code for multiple hours straight, then debug everything afterwards.
Knuth wrote TeX in a notebook and did not test it for a good six months afterwards, though I am not aware if he was out of college at the time.
> I have never seen any half way decent developer write code for more then a few minutes without some sort of feedback, automated test suite or not
Reading that again, I'm sorry if it came off as sort of attacky, but I really meant that as a "from my personal experience with the people I have worked with over my career" type qualification :)
I can buy #1, but only when it is something you've done a bajillion times before. When you are getting feedback every few minutes, you know exactly what introduced the problem, and don't waste time tracking things down. If you do miss something fundamental and have several hours work behind you, you tend to be more inclined to hack out something to make it work, where if you catch it a few minutes in, you can adjust your design to take it into account. I also find I can keep in the flow pretty easily with constant feedback, and I use simple todo lists to make sure I don't lose track of things.
As for 2, at least for me, I don't think there is any comparison between thinking about how things should work, and knowing if things do work before writing. TDD is definitely not a replacement for deep thought and planning, but I think that is a different beast then working out the details as you are writing them, which is where it comes into play
> only the people out of college write code for multiple hours straight, then debug everything afterwards.
I sort of did it again there, I should have qualified it more :) In my experience, the better programmers I have worked with, paired with, and watched code in videos will get feedback as quickly and often as makes sense, be it with tests or without them. I know if I wrote TeX in a notebook, it would be a guaranteed unmitigated disaster :)
I think most of you guys missed the point. Writing tests is very important WHILE writing code, to write it better.
We MUST write tests not only to catch regressions, to be sure that certain invariants will be manteined. But we write tests to check if we are writing good code.
I need to write a class to do some stuff. The test is the first user of this class. If I cannot write the test very fast, and I see that I'm spending a lot of time doing it, this means that my class is poorly designed, is not flexible, is not very reusable. Maybe I'm doing something wrong with my app design. If I'm writing good code, reusable and clean code, testing is easy and fast.
Testing help me to check immediately what's going wrong with the code, not only in term of bugs.
That's the point I was trying to make. The main benefit comes from eliminating the "run/debug" part of the "code/run/debug" loop. It then just becomes "code/test" where "test" takes all of a couple seconds each time.
A couple of seconds is too long. I run a small test suite in a couple of microsecs every time I save a file, and save my file at every change. When a task is done I run all the tests.
But surely if you have written a unit of code, you should at least know a. What valid input the code should have, b. what output the code should return, and c. What you want he code to do! If you know these things, then wouldn't it be easy enough to write tests for at least these conditions?
It's not that. I wrote a fairly complex piece of code in, of all things, TSQL, and as the logic was unfortunately in the stored procedures and functions I actually found that the unit tests I did for the more granular functions saved me a lot of time. This was because I would make a change to the logic of a function that other functions/procs relied on and the. All of a sudden I would find that a whole bunch of tests on functions that worked before started failing. I'd never have known this without the tests that DID work previously. Saved me a lot of time I can tell you :-)