Live data from Hacker News

Why TDD isn't crap

hillelwayne.com

111–120 of 171 posts

Re: Why TDD isn't crap

#111
post #8

Like the author, I subscribe to the less strict view that TDD isn't necessarily about writing the test first, but rather about having test play some part in how the code takes shape. Unlike the author, I absolutely believe that tests are about design. More specifically, they're about identifying coupling so that you can reduce it. The function being "awkward" to use is part of it, but code which is hard to test is al…

I've always thought that the bulk of the value of tests is for the unfortunate person who has to refactor or extend your code years down the track. By that logic, if you write testable, but untested code, then you're still making it difficult for people to refactor later. This applies even if the code is well designed and uncoupled.

Many times that unfortunate person is you just a month or two later.

Re: Why TDD isn't crap

#112

The only thing I disagree with in this article is the leeway given to supposedly legendary programmers who can somehow write bug-free code without tests, specifications, or an inkling of communication with others. First, it's probably not true. Linus Torvalds is not a legendary human being who can write critical systems without a single flaw. He relies on legions of human beings to carefully check and review every li…

Not disagreeing with your overall message, just want to point out something that bugs me and you're not the first one I heard saying something like this: "They provide theorems in the form of examples". This is incorrect. Theorems are deductive while test are experimental and this is a crucial difference in my opinion. To give and example: say we have our function isDAG :: Graph -> Bool, which determines whether a graph is a DAG, and we want to _prove_ that it works then no amount of experimental test cases will be sufficient. In real life, however, most of us (including me) settles for having _some_ confidence in the correctness of our code by utilising tests.

Re: Why TDD isn't crap

#113
post #35
post #8

Like the author, I subscribe to the less strict view that TDD isn't necessarily about writing the test first, but rather about having test play some part in how the code takes shape. Unlike the author, I absolutely believe that tests are about design. More specifically, they're about identifying coupling so that you can reduce it. The function being "awkward" to use is part of it, but code which is hard to test is al…

"having test play some part in how the code takes shape" That is exactly the point why I don't like TDD. I mean, there are enough constraints that shape the code, why should something artificial like tests shape it too? With mocking and everything you end up writing code for tests and not code for your problems.

I don't consider taking steps to make sure the code actually as you expect it to as "artificial" feels pretty essential, to me.

Re: Why TDD isn't crap

#114
post #82
post #41

Earlier quoted context omitted.

If you use mocks extensively in your tests then you probably aren't getting much of the benefit of TDD. Mocks indicate high coupling so using them is just powering though testing your bad design rather then driving good design via testing.

How do you handle dependencies of the class under test then?

This is the biggest challenge. What I find works is separating your orchestrations from your data processing.

For example, instead of creating one class that does the network call, and processes the JSON response, break these out.

One class does the network call (keep it extremely thin). Dependency inject stuff in if you want. But view this purely as an orchestration.

if (connectionValid) json = makeNetworkCall anotherObject.processJson(json) Then, in the other plain old data process class, do you heavy off-by-one edge case testing there.

If the first case, the orchestration, I can write tests like "One make the network call if the connection is valid". But that's all that test would do.

I am at the point now where I actually don't even test that. I assume that is going to work, because it is so simple. That and I generally hate mocking. Way too much coupling. Way too hard to refactor.

Where I do test heavy is on the plain old object side, that has no outside ports or connectors. These are just plain old objects.

I agree with some other comments I have ready here. Mocking is a bitch and I generally don't like it. But it's there if I needed it, so I do use it occasionally.

But it has so many downsides I try not to. Instead I separate the orchestrations from the processing. Unit test the processing (in an integration test sort of way), and try to stick to testing the public APIs of my class, so I am free to change the internals without things breaking.

My 2c. Hope that helps.

Re: Why TDD isn't crap

#115
post #8

Like the author, I subscribe to the less strict view that TDD isn't necessarily about writing the test first, but rather about having test play some part in how the code takes shape. Unlike the author, I absolutely believe that tests are about design. More specifically, they're about identifying coupling so that you can reduce it. The function being "awkward" to use is part of it, but code which is hard to test is al…

How do you test your test if you don't write the test first? If you write the code, and then you write the test, then you haven't tested your test. You have no proof that your test will detect broken code. The only way to prove that your test can detect broken code is to run it against broken code. So you can write the code, then write the test, and then break the code and run the test. Or you could just write the te…

Although on the other hand, writing your test first with no code and having it fail isn't really telling you much about the test. It just shows that the test handles the least interesting case (the case where there exists no code). You still don't know that your test is correct when you get it passing. You just know that it is correct when no code exists.

For example,

    TestSort(ISorter sorter)
    {
        var input = { 1, 2, 3, 4 };
        var output = sorter( input );
        Assert.IsSorted( output );
    }
This test will fail if you run it before the ISorter is implemented. But then it will pass if you implement an empty ISorter because the test still has problems (ie it starts with sorted input).

Cue the ever familiar: You still have to use your brain when using TDD.

If TDD needs brain usage to function, maybe the real thing that is useful is the brain usage and TDD is vestigial.

Re: Why TDD isn't crap

#116
post #8

Like the author, I subscribe to the less strict view that TDD isn't necessarily about writing the test first, but rather about having test play some part in how the code takes shape. Unlike the author, I absolutely believe that tests are about design. More specifically, they're about identifying coupling so that you can reduce it. The function being "awkward" to use is part of it, but code which is hard to test is al…

> code which is hard to test is almost always going to be hard to maintain

This is a pointless equivalence to make. You're trying to suggest that code which is hard to test could be written differently, and better. This is not always true, and therefore useless to say.

STUXNET was very difficult to test. Reports are that it required an entire Israeli nuclear facility as a test environment. Would you suggest that STUXNET was written to a substandard level of professionalism? I doubt it.

Re: Why TDD isn't crap

#118
post #92
post #85

Earlier quoted context omitted.

Look up the talk "what we know about software engineering" on YouTube. Also, search for Mills, Cleanroom, and obviously Capers Jones as I mentioned. I'm on my phone so I can't link a lot, but I maintain that the author should do a lit review of software quality in engineering, and they'll get better conclusions

TDD is only ~15 years old. Cleanroom and correct-by-construction both have some solid studies supporting them, but take very different approaches than TDD does. They tend to be more rigorous and also take longer so again, it's a case-by-case basis thing.

> They tend to be more rigorous and also take longer so again, it's a case-by-case basis thing

I'm not sure if we're taking away the same things from these studies, as their whole conclusion is it actually takes less time and costs less, due to early wins in quality. The papers claim it's not a case-by-case thing.

Re: Why TDD isn't crap

#119

Earlier quoted context omitted.

When TDD first started coming out years ago, in an email thread I asked one of the proponents how they handle the fact that tests can easily increase the complexity of a system by adding more code. I was expecting a rational discussion of how to balance tests making your code simpler with tests be a source of added complexity. Instead it was met with anger because I should "count" tests as part of the codebase, and h…

> I asked one of the proponents how they handle the fact that tests can easily increase the complexity of a system by adding more code. Adding more code != more complexity. Complexity comes from high coupling between code, that doesn't separate concerns, which make it difficult to untangle, aka. spaghetti. Unit tests are mean to be simple, and anything they test will be no more complicated that how the system will ac…

Again, this is the argument made to me over 10 years ago, and again, they are wrong. While it is possible to add more code and not get more complexity, it is very difficult. Generally speaking, adding code adds complexity. Full stop. Excellently executed TDD will reduce overall complexity, but I almost never see that level. Rather, TDD's ability to catch bugs is mostly enough to reduce bugs (and other benefits) overall. But the costs are high.

Re: Why TDD isn't crap

#120
post #8

Like the author, I subscribe to the less strict view that TDD isn't necessarily about writing the test first, but rather about having test play some part in how the code takes shape. Unlike the author, I absolutely believe that tests are about design. More specifically, they're about identifying coupling so that you can reduce it. The function being "awkward" to use is part of it, but code which is hard to test is al…

> code which is hard to test is almost always going to be hard to maintain This is a pointless equivalence to make. You're trying to suggest that code which is hard to test could be written differently, and better. This is not always true, and therefore useless to say. STUXNET was very difficult to test. Reports are that it required an entire Israeli nuclear facility as a test environment. Would you suggest that STUX…

You're missing the word "almost". It's important. Attacking parent comment with an absurd statement no one would agree with isn't a great argument.

He literally admits it's not always true in the sentence

Post reply on HN