"I have often compared TDD to double-entry bookkeeping."
It always seemed to me, if you were to make perfect, automated tests that 100% cover your application, you would basically have reimplemented it. (Or in other words - if you want to check if your calculations are correct, you have to do the calculations again.) Ideal, fully automated tests are basically taking two implementations, run them side-by-side, and compare the results.
That's why I am not a big fan of tests, in the sense that there is too much focus on them in the SW industry, and they seem like a hammer (useful but overused).
I think there should be more focus on writing the _one_ implementation correctly. This can be done with better abstractions (e.g. actor model for concurrency, functional programming, ..) and asserts (programming by contract), and maybe even automated SW proving. I don't think these techniques are as popular as testing, but I wish they were more popular, because they let you write programs only once and correctly.
[Update: To specifically expand on point about asserts, if you can trivially convert test to assert, why not do it? Unfortunately tooling doesn't support asserts as much as tests.]
You're right in a sense; in TDD, you're basically saying a thing, and saying the inverse of a thing, and then making sure they line up. I find that my codebases are about 50% test code and 50% production code.
Your implication that this is wasteful is wrong, though. My production code is smaller when I work this way because I do more refactoring, and for projects that live longer than a month or two, I go faster.
By the way, TDD is absolutely in the same vein as design by contract and formal proofs. Both involve saying the same thing twice, in two different ways. TDD is a sloppier, more practical version of the same basic idea. See "Worse is Better."
Yes, some people argue that your tests are more like a specification, so imagine that every feature would have tests. Some even argue for specifying things like constants, which runs contrary to what Martin says in this article.
Overkill, IMHO, but tests have their place.
I tend to look at it now as test stuff that's being used often or stuff that may break easily when I'm making changes. At a certain point, automation of key tests make sense if you're wasting too much time manually testing.
Comments
"I have often compared TDD to double-entry bookkeeping."
It always seemed to me, if you were to make perfect, automated tests that 100% cover your application, you would basically have reimplemented it. (Or in other words - if you want to check if your calculations are correct, you have to do the calculations again.) Ideal, fully automated tests are basically taking two implementations, run them side-by-side, and compare the results.
That's why I am not a big fan of tests, in the sense that there is too much focus on them in the SW industry, and they seem like a hammer (useful but overused).
I think there should be more focus on writing the _one_ implementation correctly. This can be done with better abstractions (e.g. actor model for concurrency, functional programming, ..) and asserts (programming by contract), and maybe even automated SW proving. I don't think these techniques are as popular as testing, but I wish they were more popular, because they let you write programs only once and correctly.
[Update: To specifically expand on point about asserts, if you can trivially convert test to assert, why not do it? Unfortunately tooling doesn't support asserts as much as tests.]
You're right in a sense; in TDD, you're basically saying a thing, and saying the inverse of a thing, and then making sure they line up. I find that my codebases are about 50% test code and 50% production code.
Your implication that this is wasteful is wrong, though. My production code is smaller when I work this way because I do more refactoring, and for projects that live longer than a month or two, I go faster.
By the way, TDD is absolutely in the same vein as design by contract and formal proofs. Both involve saying the same thing twice, in two different ways. TDD is a sloppier, more practical version of the same basic idea. See "Worse is Better."
Yes, some people argue that your tests are more like a specification, so imagine that every feature would have tests. Some even argue for specifying things like constants, which runs contrary to what Martin says in this article.
Overkill, IMHO, but tests have their place.
I tend to look at it now as test stuff that's being used often or stuff that may break easily when I'm making changes. At a certain point, automation of key tests make sense if you're wasting too much time manually testing.