Live data from Hacker News

TDD did not live up to expectations

blogs.msdn.microsoft.com

331–340 of 450 posts

Re: TDD did not live up to expectations

#331
post #145

The tests get in the way. Because my design does not have low coupling, I end up with tests that also do not have low coupling. Not to be smug, but I feel like this is a rookie mistake I learned 10 years ago immediately after starting TDD. The slogan I use in my head is that testing calcifies interfaces . Once you have a test against an interface, it's hard to change it. If you find yourself changing tests and code A…

This is terrific. You know, I've spent the last ten years perfecting coding strategies around unit test frameworks and mocks. I'm really really good at that. Really. I won't be humble; if somebody wants this, then I'm one of the best in the business. Yet, I'm slowly coming to the realization that that's a perfectly useless skill. Perhaps, even a negative skill.

It depends on the project, but for most projects I've worked on, the most difficult parts are the integrations with external systems. Figuring out what headers you need to pass in a call to Facebook, or what certificates you need to access some third-party API, or what data to send over USB to activate some device. Unit tests / mocks let you blithely ignore all those things. You mock them out, hide behind an interface, write your "application code" that uses these interfaces to do whatever your application does, make unit tests with mocks that behave the way you'd like, and viola your app is done! With almost 100% code coverage even! And it's even fairly well-designed with fairly low coupling. Except, it doesn't work at all, the hard work is still ahead of you, and your interfaces are all probably leaky abstractions that you're going to have to change substantially to make it work for real.

Anyway that's the hole I've dug for my current project. I'm pretty quickly coming to the conclusion that I need to unlearn quite a bit, retrain my instincts. I like your posts. Not even much for the content, but mainly for the concept. Rather than cargo culting onto "unit-testing-in-framework-X-to-achieve-100%-code-coverage-because-that's-how-you-make-sure-your-app-works,-right?", it's more of an intentional approach. Step 1: determine what we really need to make sure of, step 2: determine the best way to achieve that.

Ultimately, what I think is wrong with TDD as most people know it, in a word, is that it's a shortcut. It's easy. You populate your mocks with fake data and it's infinitely repeatable so yay. Populating an actual database with fake data and making sure it's deleted/refreshed/whatever between tests is difficult. But that doesn't mean it's not the right thing to do.

Re: TDD did not live up to expectations

#332
TDD supports the paradigm of Software Engineering as an Engineering field. Design, plan, build, test.

Chartered Engineers have qualifications for their skills to do this - whether it's building bridges, designing circuits, or making cars.

Most programming is not Engineering. It's scripting. Hacking together a quick solution to meet the user's immediate needs.

Huge businesses (including the company I work for) have some really weak points in their production flow. They're planning factory operations using some shoddy macros in Microsoft Excel thrown together by some businessperson with no programming experience. Management won't change it, because "it works".

Other fields of Engineering (civil, electronic, mechanical) have serious life-threatening consequences if they fail. Software rarely has that risk. (Insert comment about healthcare systems and WannaCry here).

For times when software carries serious risk, then TDD is still important! The rest of the time, it's a burden.

Re: TDD did not live up to expectations

#333
post #16

TDD never worked for me, I believe because of the nature of my work: research code, very explorative in nature. I do not now in advance how the interface will turn up, so it's hard to anticipate the interface in my tests (or it leads to a lot of wasted). Nowadays I mostly test with "redundant random generation testing": generate random but coherent input, run logic, then... Either I can reverse the logic, and I do th…

My former lab tried to use TDD. I've come to the impression that it's not the right approach for science / prototyping and just bogs you down. I don't think that science should eschew testing completely- I just think that something like your "redundant random generation testing" is more in line with what needs to go on. The trickier issue is changing your lab culture so that it actually understands the need to run te…

This is funny, because as a consultant, I think to myself "TDD really doesn't work for me, because I've got so many 3rd-party dependencies that I have to mock out in my tests (which often makes unit tests seem more like a test of your mocks than of your actual application); TDD must really be best for researchy things where they don't have to deal with those problems".

Re: TDD did not live up to expectations

#334
post #319

The main benefit of TDD: It strongly encourages you to think of your code as several input/output problems. When you apply this model of thinking at scale it tends to lead to a much simpler (read: less-complex) codebase.

This is the top-level comment that resonated most with the point I wanted to make.

TDD is good for training you to recognize untestable code. "Oh, yeah, that's a Law of Demeter thing... maybe we should just ask for the narrow object rather than the giant one that knows how to get the narrow one," etc.

Once you have that skill ingrained, it's reasonable to stray from strict TDD and simply remember to defend your code with adequate tests.

Re: TDD did not live up to expectations

#335
post #82

Earlier quoted context omitted.

I've never heard TDD being that you write all of your tests up front, before you've written any code. I've always heard it as: When you're writing a class/unit, you write a few tests for what that unit is going to do. You then make those tests pass. You add some more tests, make those pass, and so on and so on.

> I've never heard TDD being that you write all of your tests up front, before you've written any code. That's the only way I've ever heard it described. I thought that's why it's called "Test Driven "

[deleted]

Re: TDD did not live up to expectations

#336
post #76

Maybe the title should be: TDD did not live up to my expectations ? 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 yourse…

> 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 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 fu…

If you don't know the domain/range of your function, and you are forced to write tests in advance, then you will end up specifying a domain/range. The worry here is that you pick a domain/range that is really inefficient, and you write 'bad' code to support it, and you can't refactor it out without more overhead later.

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...

Re: TDD did not live up to expectations

#337

Earlier quoted context omitted.

Nothing. There is nothing wrong with code generation in a production setting with "grown up" engineers who uses version control and knows the pitfalls. The part in parenthesis is just a rant about education and how teachers use notepad and javac to teach Java. So my point is the only thing students shouldn't use in an IDE is code generation.

But going from javac to Maven in CS1 would be insanely difficult; there are many prerequisites before one can use Maven. It may only work in top-tier schools.

I'd say quite the contrary:

If I had been given a zip with a basic pom file and the correct main and test directories I think I'd had a much simpler start.

Re: TDD did not live up to expectations

#338

TDD failed for economic reasons, not engineering ones. If you look at who were the early TDD proponents, virtually all of them were consultants who were called in to fix failing enterprise projects. When you're in this situation, the requirements are known. You have a single client, so you can largely do what the contract says you'll deliver and expect to get paid, and the previous failing team has already unearthed…

Author here... I agree that time to market is really important, but when a company is searching for the product that will work, the most important thing that you can have is code that is easily refactored, which generally means low coupling. TDD is one way to get there for some people, and it's not 2x the amount of time. My experience is that TDD takes a little bit longer (say 30%) than just writing the code, but my…

Well, there's time you save on testing.

TDD gives me quick feedback. Its faster to run unit tests vs deploying and testing the functionality. I'd say TDD adds very little or no overhead.

Re: TDD did not live up to expectations

#339
It’s important to not assume that tests and code will be written by the same person.

When tests are being created early, it’s actually a good excuse to have at least a couple of minds looking at the same problem, instead of bottling it up into one person who ends up quitting next month. It’s an excuse to not just discuss the approach to use but have some code, where each person may realize that they hadn’t really thought about the whole problem or maybe didn’t understand it at all.

Other criticisms in this thread are still fair. It is certainly possible to waste a lot of time on tests for instance, and to build something that is too restrictive. Ultimately though, if you’re more than a one-person project, some form of “sketch it out first” is a good thing.

Re: TDD did not live up to expectations

#340

Earlier quoted context omitted.

> TDD always worked for me. > All successful projects in my career had full functional regression test coverage. Regression testing is not the definition of TDD, however. TDD is this crazy religion of writing tests for everything, including the lowest-level helper functions in a module that don't correspond to anything that would be tested in a regression test suite. You write these little tests first (which must be…

> TDD is this crazy religion of writing tests for everything, Not true in my experience. You should only test code you wrote that can break. You do not test core functionality, the OS underneath etc. You do not test the test themselves.

No, TDD means that if there is a line of code anywhere that was not written to make some failing test pass, that code is by definition broken. ALL code must be against some test, else it's not TDD. And if you want to write code for which there is no test, you must write the test first, run the test suite to see it fail, and then implement the code that will make the test pass.

Anything else is not TDD.

Post reply on HN