96

Test-driven development (TDD) is big these days. I often see it recommended as a solution for a wide range of problems here in Programmers SE and other venues. I wonder why it works.

From an engineering point of view, it puzzles me for two reasons:

  1. The "write test + refactor till pass" approach looks incredibly anti-engineering. If civil engineers used that approach for bridge construction, or car designers for their cars, for example, they would be reshaping their bridges or cars at very high cost, and the result would be a patched-up mess with no well thought-out architecture. The "refactor till pass" guideline is often taken as a mandate to forget architectural design and do whatever is necessary to comply with the test; in other words, the test, rather than the user, sets the requirement. In this situation, how can we guarantee good "ilities" in the outcomes, i.e. a final result that is not only correct but also extensible, robust, easy to use, reliable, safe, secure, etc.? This is what architecture usually does.
  2. Testing cannot guarantee that a system works; it can only show that it doesn't. In other words, testing may show you that a system contains defects if it fails a test, but a system that passes all tests is not safer than a system that fails them. Test coverage, test quality and other factors are crucial here. The false safe feelings that an "all green" outcomes produces to many people has been reported in civil and aerospace industries as extremely dangerous, because it may be interepreted as "the system is fine", when it really means "the system is as good as our testing strategy". Often, the testing strategy is not checked. Or, who tests the tests?

In summary, I am more concerned about the "driven" bit in TDD than about the "test" bit. Testing is perfectly OK; what I don't get is driving the design by doing it.

I would like to see answers containing reasons why TDD in software engineering is a good practice, and why the issues that I have explained above are not relevant (or not relevant enough) in the case of software. Thank you.

CesarGon
  • 2,981
  • 55
    Bridges, cars, and other physical designs are nowhere near as malleable as software. This is an important distinction, and means that comparions between software and real engineering isn't always relevant. What works for bridges might not work for software, and vice versa. – Lars Wirzenius Jan 30 '11 at 13:29
  • 1
    @Lars: The belief that software is more malleable than other types of things is very extended; however, some prominent people have been saying that "software is not soft" (google it). Also, I would dispute your reference to software vs. "real engineering". :-) Care to elaborate? – CesarGon Jan 30 '11 at 13:33
  • 9
    I somewhat agree with your doubts. I've for example to confess I got the impression that having a test suite can have as a side-effect a somehow "softened" attention when writing code. Of course tests are a good thing (a mandatory one if you want to have the possibility to refactor), but only if they supplement the attention to details, border cases, efficiency or extensibility and not if they replace it. – 6502 Jan 30 '11 at 13:56
  • 2
    @6502: By all means! TDD is not a silver bullet and will not solve all issues that arise during software development. It is however a useful method of organising workflow. You can for example impose a requirement that all border cases are covered by tests. You still need to know what these border cases are, but now you also have a tool to check if your code deals with them correctly. – Mchl Jan 30 '11 at 14:01
  • 2
    @CesarGon, you might also be interesting in this question I asked on SO some time ago... Not quite TDD, but related... Some very enlightening answers there. – AviD Jan 30 '11 at 23:31
  • TDD works iff there is enough time in the project! – Amir Rezaei Jan 31 '11 at 07:54
  • 1
    TDD (and the larger agile movement) is about reacting to change. Let's hope bridges and cars have less change after the work has begun than a typical software project! – Brad Cupit Jan 31 '11 at 18:53
  • 1
    @Amir Rezaei: This might be the case on short term view. This is always false on longer time spans. – mouviciel Jan 31 '11 at 19:06
  • 6
    How amazing that a civil-engineering/software-development analog doesn't hold up. Along the same lines, I've often noticed that I can't cook pancakes the same way that I mow my lawn. –  Oct 21 '11 at 13:52
  • 1
    You see the final result of a car and don't think there were a lot of crashes and hacked up prototypes? Just because code goes throught several iterations, doesn't mean all the mess is included. – JeffO Oct 21 '11 at 14:01
  • 1
  • A bridge costs much more to build than to design. Software if the exact opposite. Building it is, at most, the cost of a minute's worth of CPU time. 2. I hate Test Driven Design. Test Driven Development is much better. Design first, then test, then implement. You end up with a much better architecture.
  • – RubberDuck Feb 19 '16 at 00:09