1. 15
  1. 14

    “when the tests all pass, you’re done”

    Every TDD advocate I have ever met has repeated this verbatim, with the same hollow-eyed conviction.

    Citation strongly required. If it was something being repeated verbatim it should be all over the internet. But when I search for the phrase in quotes I get.. versions of this blog post.

    In my experience the first thing TDD teaches is that testing is a process. Every time you want to make a change you write a test first. Where’s the “done” in that?!

    Forget “every”, and forget “verbatim”, I’d like to see one person advocating for something resembling this thesis.

    1. 9

      I don’t know a good way to cite this well, but I have had the same experience as the author with regards to TDD-minded folks. I also want to stress that I’m in a camp that likes having thorough unit tests, but disagrees with TDD for more or less the reasons that the article specified.

      1. 1

        Thank you. I definitely appreciate that experience can vary. As long as you’re writing automated tests the details are much less important.

    2. 26

      This feels like outrage baiting to me.

      1. 1

        Me too.

        There’s only so many “I don’t understand X so it must be bad” stories the intertubes can come up with each week, right? (Please say right)

      2. 7

        What the author describes is fundamentally wrong. It’s just not TDD, more the antithesis of TDD.

        In TDD, you don’t “write all the tests” and start implementing. That’s waterfall with tests.

        You write a, make that pass, refactor, see what you have learned, rinse repeat.

        1. 6

          This article just screams flamebait to me. Personally I don’t think TDD is the correct way to do most software either, but this reads like the author has a level of understanding about the process that would be… uncharitable of me to assume.

          1. 6

            I’m going to say this because I am a sucker for outrage tech porn. I also like trying to see how terse I can make a technical explanation.

            TDD is not testing. TDD is a design activity for incremental OOP. Testing is simply one of the many byproducts.

            If you got that, you understand why TDD doesn’t have to have total coverage, why it’s probably overkill for some projects, and so on. If you still think it’s some weird version of backwards unit testing you have a long way to go.

            1. 4

              I’ve tried Test-Driven Development a few times, but I generally don’t use it: it hasn’t struck me as worth the constraints. However, I do not agree with this article’s argument against TDD. The article misunderstands how TDD is supposed to work in ways that kill its entire argument.

              Wasted test code?

              The author argues against TDD on the basis that “every single revisit of the TDD tests is 100% wasted time”. But according to the theory of TDD, this is not true. The idea is that you write tests against your code using the API you plan to implement, e.g. logMessage(true, "something went wrong"). Then you notice one of the “unanticipated contingencies” the author mentions, because the planned API looks wrong. Then you rewrite your tests, e.g. logMessage({error: true}, "something went wrong"). At this stage you haven’t implemented anything, so though you had to rewrite your tests, you don’t have to rewrite your implementation of logMessage.

              In other words, the author says that TDD works like this:

              1. write the TDD tests
              2. begin implementation
              3. discover an unanticipated consideration [within your implementation]
              4. rewrite the tests
              5. continue implementation
              6. goto 3 over and over and over …
              7. (actually more like item 150) all tests pass

              But according to TDD, it would actually go more like this:

              1. write the initial TDD tests
              2. discover an unanticipated consideration thanks to your tests
              3. rewrite the tests and change your plans
              4. begin implementation (using your refined plans)
              5. discover an unanticipated consideration within your implementation
              6. goto 2 or 4, not too many times
              7. all tests pass, and you are confident your design is good

              Rewriting the tests still does have a cost, certainly. But TDD vs. tests-after-code is a tradeoff, not a matter of one option being strictly better. To a first approximation, TDD is better if you think that, for the average problem you will discover in your code, ((probability that problem will be revealed by writing your tests) × (effort to solve the problem within the tests)) < (effort to solve that problem within the implementation)

              TDD and refactoring

              Apart from helping your design by showing you what the tests look like, TDD is supposed to have another advantage: refactoring your code being easier with the safety provided by your tests. (TDD’s mantra is “red, green, refactor.”) So with TDD, you can refactor your code in the middle of implementing it, and compared to refactoring before tests are written, you can have more confidence that your refactoring didn’t break the implementation you wrote so far. I don’t feel like analyzing the value of that benefit right now, but it’s another aspect any argument against TDD should consider.

              Developers writing their own tests

              The second problem here is that TDD presumes that developers should write their own tests. This is supremely ridiculous. … The same blind spots that I had in design will appear in my tests. … Everyone’s work needs to be blackbox-tested by someone else testing against the requirements and functional specifications.

              Of course the code author will find fewer flaws in their code than a different developer, if you give that other developer enough time to understand the structure of the code and test it. But this assumes that another developer or a QA department is available.

              There are classes of developers for which external testing is not feasible: solo developers (especially ones working on personal projects) and young startups. How should they work? TDD prescribes itself as useful for those people, so it’s still worth discussing whether, for those people, it’s better to write tests first or last (or not at all).

              1. 3

                This doesn’t feel like the author has actually found good information on TDD, but that they are reacting against a meme.

                I’ve not used perfect TDD as of yet, but tests are valuable for both informing your design and for making sure that you don’t have regressions.

                Working Effectively with Legacy Code is pretty essential reading for this, in my opinion, and I’ve like the article on the MoonPig billing system as well.

                1. 2

                  TDD (when applied with some sense, i.e. practically rather than dogmatically) is easily the most silvery bullet I’ve seen in my 20 years of developer life. Sure, bad processes are still bad, it doesn’t fix that.

                  1. 2

                    My work was essentially finished, the final application was very small, only a few screens of code. I was instructed to write unit tests for it just so managers could check a box; I resisted because the project was too small to have any units and tearing it apart to add these silly tests would mean destabilizing work that had already passed all tests and was ready to release.

                    Reading this opening paragraph made me take everything after these first few lines, i.e. the entire article, with a grain of salt. “Tearing apart a project and destabilizing work already passed all tests” suggests the author writes highly coupled code with high cyclomatic complexity that could easily be destabilized. It also suggests the author lacks a nuanced perspective about what functions should be tested and how.

                    Part of me sympathizes with the author – exclusively writing unit tests with testing frameworks like JUnit or the like makes me go crazy due to silly, repetitive, and often unreadable test framework structure/organization. But using a BDD framework like rSpec to TDD I find is useful and can help drive forward development of challenging features.

                    1. 0

                      Flagged as off-topic for the straw-man fallacies, the argumenta ad hominem, and the moral superiority virtue-signalling.

                      1. 6

                        That doesn’t make it off-topic.

                        1. 0

                          Which flag reason do you think is more appropriate?

                          1. 3

                            “hide” maybe? Or perhaps just a comment that you thought it was a bad article?

                            1. 1

                              I usually use hide when it’s a post that I’m not interested in, but I don’t think is off-topic for the site. I may be misusing it that way; I’m not sure.

                      2. 1

                        something new called “Test Driven Development”

                        New, in 2008?

                        1. 1

                          Well, you can write good tests and bad tests.

                          Writing good tests is difficult, and hard work.

                          Saying “Test-Driven Development is Fundamentally Wrong”, is like saying “C++ is Fundamentally Wrong”, or “Perl is Fundamentally Wrong”, because it is hard to write good C++, or good Perl, …

                          There is not really much of a point in the argument of the article linked above, … it is more like a frustrated rambling, …

                          1. 1

                            The author mentions ‘the tests’ several times, as if all tests are equal. I agree with the author to some degree if he solely means unit tests.