The way I put it: "if I don't know the domain and range of my function, I shouldn't be writing code yet, I should be investigating the problem."
TDD is for unit tests, and unit tests best test functional, stateless code--the functional, central logic of your application is what you should be specifying and writing unit tests for, not all the imperative stuff wrapping it for IO and failure catching and the like (Gary Bernhardt[1] calls it scar tissue).
Now, this is a minor issue. It's probably more worth it to build inefficient interfaces now and try to fix them later than to never build anything because you don't know what the optimal design is. I can't say if TTD gives a real advantage there, but when designing-while-coding-with-no-tests, you end up playing with the interfaces, changing them regularly, and learning something about why they are the way they are. Which is possibly a better process when you don't have any relevant design experience? I really don't know...
Never heard anyone say this. Kent Beck has said the opposite on podcasts.
This is the most beneficial part of TDD to me. Most devs will deny this, but their biggest issue with TDD is not wanting to take the time to think clearly about a problem. To me that seems a bit sloppy and lazy. We're supposed to be professionals. From some of the comments I've read, it also seems that devs are trying to "test drive" or write unit tests for the wrong things. As I've gained experience as a software developer, I actually look for ways to write less code. The most effective way for me to do that, is to actually think about the problem before I write a single line of code. If I have a clear idea of what it is I'm trying to build, it's very easy for me to write a test first. If I can't identify a way to write a failing test, it's an indication to me that I really don't understand the problem well enough to deliver a dependable solution.
Design by Contract specifying key properties at interfaces with tests for stuff not easy to specify was state of the art in the 90's. In the 2000's, there's tools to automatically generate tests from such properties or apply formal proofs to code if it's simple enough. I don't see TDD as either strongest method or state of the art. DbC, assertion/property-driven testing, some fuzzing, and proving /model-checking for most important components collectively seem state-of-the-art for realistic software. Most of which is just automated versions of manual methods invented in the 50's-60's. Most being 60's with fuzzing going back to 50's.
One from later time I like since it consistently got low defect rate was Cleanroom. Here's a good explanation of it.
> I don't see TDD as either strongest method or state of the art.
It's not the strongest method. But as far as the SWEBOK[0] is concerned it is state of the art.
The most effective teams I've worked with layer their testing strategies and use multiple approaches to verification depending on the needs of the project. I love quickcheck. I even pull out formal methods when the problem domain demands it or I need to check my thinking.
On the scale of "sketch on a napkin" to "verified and signed-off-by-master-engineer blueprint" I'd say a unit test suite, as far as it is a specification, is somewhere between napkin and the middle. If you use a soundly typed language AND a unit test suite using property-based assertions you're somewhere in the middle; building houses.
However I do see it as a warning sign if a team actively avoids TDD and tries to ship the first thing that works. If I was an actuary that project would represent a high level of risk and I'd probably raise their insurance rates to match that risk depending on the work they're trying to do.
I think that's part of the point. If you want to follow a process like clockwork, test-implement-refactor-test, then TDD might be the best we have.
But what if not having any process is better than even the best formalised process? That's certainly my personal experience: my haphazard, process-free way of hacking delivers solid results very fast.
That is the title. If you are arguing that explicitly specifying "my expectations" would significantly alter its meaning, I disagree. Otherwise, whose expectations were we to assume TDD did not meet?
Without qualification, I would expect those of the people choosing to adopt TDD generally.
Yes.
> Or other projects where the design is highly likely to change or be discarded?
I don't often just start writing code without thinking about the design of the system or module I'm working on. Unless I'm writing a one-off shell script or some simple elisp glue code... I write the tests first.
I too, like the author, have been practicing TDD for > 10 years. Test, implement, refactor, test... that's the cycle. If you follow that workflow I've never seen it do anything to a code base other than improve it. If you fail on the refactor step, as the author mentions, you're not getting the full benefit of TDD and may, in fact, be shooting yourself in the foot.
I've read studies that have demonstrated that whether you test first or last doesn't really have a huge impact on productivity.
However it does seem to have an impact on design. Testing first forces you to think about your desired outcomes and design your implementation towards them. If you think clearly about your problem, invariants, and APIs then you will guide yourself towards a decent system.
The only failing I've seen with TDD is that all too often we use it as a specification... and a test suite is woefully incomplete as a specification language. A sound type system, static analysis, or at the very least, property-based testing fill gaps here.
But for me, TDD, is just the state of the art. I've yet to see someone suggest a better process or practice that alleviates their concerns with TDD.