Hacker News new | past | comments | ask | show | jobs | submit login

What I never understood about TDD is: why would one have to write the test first?

Now, I get that maybe the reason is human psyche and that one may not have the same discipline to write the test after the code. But, stripping that away, more logically asking, why does the test need to exist first?

I get that if you have a test, you have an exact "plan" of what your code needs to do/return and you then work on it until the test passes.. But isn't that the case already in any strongly typed language? You constrain the set of values your function can return to only the set of all valid values by defining a type (which is that set). (Okay I may have answered my own question, as we do define the expected type first).

I think that at the end of the day it comes down to finding a balance between complete formal validation of correctness and productivity/usability i.e. actually getting something done. TDD strikes me as a practice that slows you down a fair amount yet still doesn't offer anything close to complete formal validation, so it doesn't seem that attractive to me. But I still also wonder what alternatives are out there.




You seem to be assuming that TDD is only for unit tests in strongly typed /type-extensible languages. I have seen it used for that (Scala) but also used it effectively for even integration tests in languages with limited typing (eg sql stored procedures (!) dealing with large amounts of analytical data)…

When you write the test first, you tend to think through the harder parts of “how do I make this code testable” which otherwise you might shrug your shoulders about and skip — since certain test scenarios may then require too big a refactor which is not worth it.

Just like it’s hard to bolt on security after you’ve built a product, for various system designs it’s hard to build testability if you don’t think about it up front.

The other part of this is psychological; TDD is a psychological trick for task decomposition. Certain people get paralyzed by unknown overwhelming tasks. A failing test case narrows that down to a smaller clearer solvable problem.

Also… cynically, if you write the test first, management (or your inner optimizer… you know you have one!) can’t— when they see you’ve delivered functionality— pressure/tell you to skimp on testing.

I confess I am not convinced the TDD juice is always worth the squeeze, but I have no regrets about the time I spent putting TDD in my toolbelt.


TDD is a design technique you can apply to low level or tactical coding design. Strongly typed isn't the same as a knowing and testing your inputs and outputs based on a plan or design of methods or functions. Sure, strongly typed can make that easier but it isn't guarantee it.

Testing after the fact usually means your tests a designed based on the code and not on what the code should do. Sometimes their little difference between the two, sometimes there is a large difference.

In my experience writing tests first is a slow down to speed up technique where the code is easier to write and maintain because it is tested and has built in regression testing.


The reason to write a test first is so you have automated validation that the expected behavior matches the spec. This is valuable when writing the code.

Types in a strongly typed language will not validate high level expected behavior. Types attack the problem from the bottom up instead of the top down and work by constraining the number of possible states a program can be in. You can always make types stronger and tests more comprehensive but you will be subjected to the law of diminishing returns for both the more they encroach on each others' territory.

>TDD strikes me as a practice that slows you down a fair amount

This is like saying that lunch is a practice that costs you money. Everything that validates program behavior comes with an associated cost.


"why would one have to write the test first?"

Disclaimer first: TDD won't give you anything that you couldn't instead achieve via "git gud"; except perhaps a reduced anxiety about overlooking a subtle error (but after "git gud", you don't _make_ subtle errors, do you?)

The main justification for test first is something like this: "we didn't have to be brilliantly prescient designers to find a less tightly coupled design. We just had to be intolerant of pointless effort in writing the tests." (Aim, Fire -- Beck 2000)

TDD is, in part, an attempt at reducing the length of a feedback loop. The catch is that (in spite of the labels that have been used) the feedback loop of interest is not the programming-test loop, but instead the analysis-design-programming loop (bringing OOA, OOD, and OOP closer to each other).

The underlying assumption is something like "complicate code should be easy to test". If you believe that easy-to-test drives less-tightly-coupled design, and you think that latter characteristic is valuable, then it makes a certain amount of sense to lock in that easy-to-test constraint early.

"TDD strikes me as a practice that slows you down a fair amount yet still doesn't offer anything close to complete formal validation"

Yes and... that's not TDD's job? The automated checks used in TDD are written by the developer to satisfy the needs of the developer; if the thing you want is complete formal validation, then you should be using tools designed to meet that need. TDD might give you a higher success rate when you subject candidate systems to formal validation, and should give you lower costs when revising a failed candidate, but "the TDDs passed, ship it" is _not_ a risk free proposition.

Beck again: "I never said test-first was a testing technique. In fact, if I remember correctly, I explicitly stated that it _wasn't_."




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: