Live data from Hacker News

Giving up on test-first development

iansommerville.com

171–180 of 224 posts

Re: Giving up on test-first development

#171
post #21

TDD is nuts for code without a client or specification. The whole point of tests is to ensure that the code does what it's supposed to do. When you have neither client nor spec, how are you supposed to know what the code is supposed to do ? There is, IME, a >90% chance that any such code will be ripped out and replaced as you develop a better understanding of the problem domain. I've found it's pretty useful to go ba…

I've found the opposite, that TDD helps me most when the spec or my understanding of the spec is fuzzy, by forcing me to make decisions about behaviour up-front and clarify my thinking. Otherwise I can get bogged down trying to implement and specify a feature simultaneously, or spend a lot of time implementing a feature before realising I'm approaching it the wrong way.

Depending on how you work, that can be worthwhile, but I usually find I get more useful information quickly by making the decisions that make implementation easiest, getting something up on the screen that I can react to as a user (or put in front of a real user), and then seeing where that initial proof of concept falls short. In general, I've found that pushing off decisions until I have as much information as I can tends to result in better decisions.

Re: Giving up on test-first development

#172
It is easier to test some program designs than others. Sometimes, the best design is one that’s hard to test...

Sometimes, but in my experience this is rare. Much more often, the easiest to code solution is both the hardest to test and to maintain, which is why having some TDD discipline more often results in better design, not worse.

Re: Giving up on test-first development

#173

Earlier quoted context omitted.

One good way to the limit breakage in such cases is to solely perform black box tests on the API level. In case of our Node.js based Backends we don't ever write a single classical unit test, instead we have a custom Framework built on top of Mocha which performs tests on the HTTP layer against all of our endpoints. This works remarkable well in practice and allows for large scale refactorings under the hood with lit…

Of your tests break when refactoring, something is wrong. Probably, you're testing the implementation not the behavior.

In my experience, for any non-trivial application with a non-trivial number of tests, some percentage of those tests, particular the unit tests, will have by accident or carelessness come to rely on internal implementation details that aren't reflected in the result.

Those kinds of "atrophied" tests can make a refactor considerably more painful than it should be.

Re: Giving up on test-first development

#174

Earlier quoted context omitted.

That's kind of a waste of time if you're only going to run it once and verification with a REPL or otherwise by hand is easy enough.

That's assuming it works correctly the first time (I haven't had that experience often, even for "trivial" code :( ). Even for "run once" functions, I still use a few tests to develop them and make sure my expectations are correct. With a good framework, setting up a handful of unit tests takes just about as much dev time as running the function in a REPL.

Ok, so let's say you were experimenting with the selenium library to see if you could scrape what comes out of skyscanner.

What steps would you take?

Re: Giving up on test-first development

#175
post #5

From the article: Because you want to ensure that you always pass the majority of tests, you tend to think about this when you change and extend the program. You therefore are more reluctant to make large-scale changes that will lead to the failure of lots of tests. Psychologically, you become conservative to avoid breaking lots of tests. Interesting. I've often found that the lack of tests leaves me absolutely terri…

Don't expect just because there are no test failures that you haven't broken anything. I can't stand developers who have this mindset.

Just because there are unit tests, doesn't mean they are covering all the code foremost, or that they are written properly to truly detect when things have changed for the worst.

Tests are not a replacement for actually testing and verifying your changes in whatever application gradient you're working in.

Re: Giving up on test-first development

#176
> But as I started implementing a GUI, the tests got harder to write and I didn’t think that the time spent on writing these tests was worthwhile.

I agree. TDD has it's places. Testing GUIs is often not one of them.

> You therefore are more reluctant to make large-scale changes that will lead to the failure of lots of tests.

Don't test private APIs. That makes no sense. I find quite the opposite. If I have more tests, I'm more comfortable making bigger changes, because of the safety net the tests give me.

> Think-first rather than test-first is the way to go.

Absolutely agree.

I think the "solution" to the TDD-or-not problem in Kent Beck-Martin Fowler-DHH [0] conversation was that TDD has it's places, sometimes it's really better than other and helps a lot, sometimes it just get's in your way.

[0]: http://martinfowler.com/articles/is-tdd-dead/

Re: Giving up on test-first development

#177
The author makes four criticisms of TDD:

1) That having a test suite tends to makes a programmer conservative, to avoid breaking tests. But in a team environment, this kind of conservatism is a feature, not a bug.

2) That there are cases where the code that is easiest to test is not the best code. In my experience this is the exception rather than the rule.

3) That TDD causes the programmer to focus on the details rather than the overall design. This is a valid criticism, but the way to remedy it is to build prototypes and toy code before diving into the actual implementation. Here again, if you're a lone programmer working on a pet project, you're not going to see much distinction. But on a larger project with a team of programmers, such rapid prototyping is very useful. As they say, "build one to throw away".

4) The author has trouble designing tests for bad input. I'll take him at his word, but I've never found those kinds of tests to be that difficult; if anything, they tend to be boilerplate. Certainly when you're talking about validating complex input like JSON objects, it's not trivial, but there are libraries to handle most of those kinds of real-world situations.

Re: Giving up on test-first development

#178
post #5

From the article: Because you want to ensure that you always pass the majority of tests, you tend to think about this when you change and extend the program. You therefore are more reluctant to make large-scale changes that will lead to the failure of lots of tests. Psychologically, you become conservative to avoid breaking lots of tests. Interesting. I've often found that the lack of tests leaves me absolutely terri…

One good way to the limit breakage in such cases is to solely perform black box tests on the API level. In case of our Node.js based Backends we don't ever write a single classical unit test, instead we have a custom Framework built on top of Mocha which performs tests on the HTTP layer against all of our endpoints. This works remarkable well in practice and allows for large scale refactorings under the hood with lit…

Can you say that API black box tests are strictly denoting "what" is broken, while unit and functional tests would tell you "where?"

Re: Giving up on test-first development

#179
post #11
post #5

From the article: Because you want to ensure that you always pass the majority of tests, you tend to think about this when you change and extend the program. You therefore are more reluctant to make large-scale changes that will lead to the failure of lots of tests. Psychologically, you become conservative to avoid breaking lots of tests. Interesting. I've often found that the lack of tests leaves me absolutely terri…

It's not a good argument against testing, I agree. Automated testing is a huge boon for software quality (though by no means a panacea). But TDD, in my experience, gives a slightly different dynamic. Because you generated the code being motivated by the tests, there are a lot of unit tests that don't test functional units - tests that are essentially testing implementation decisions. I've seen situations where that b…

I come to this from a test/automation engineering background and I'd like to amplify your last point.

There are a couple things to consider that sometimes become taboo in orgs--but shouldn't.

The first is that you don't need to test everything. I recommend having a great set of those API-level black box tests as an acceptance suite, but at a component or unit level you should pick your battles. If you'd architect for DI -only- to test, that testing had better be pretty necessary, otherwise you introduced complication (and risk) without a lot of benefit. That risk can actually overwhelm any benefit of testing.

The second is that you should absolutely scrap tests of implementation details at the point that the implementation becomes a black box. Tests are like scaffolding during construction, and we don't leave the scaffolding up when the building is done--we do inspections of the building instead. The same mindset should be applied to testing. Different phases need different tests, and too many tests at too low a level of abstraction absolutely cause maintenance and flexibility issues if you're not willing to let them go.

But that's no reason to back off entirely. SOME things need to be unit- or component-tested SOMETIMES. Those things generally benefit from TDD.

It's all about making intelligent decisions. There's a sometimes-controversial movement in QA/test called "context-driven testing" which comes down to there are very few always-best practices, and strategy should be tailored to your problem and situation--not done by rote, book, or prior (read, your boss's or CTO's) assumptions of what's always right. Otherwise you tend to get something more onerous than useful.

The considerations around that approach apply at the low-level test tier as well.

Re: Giving up on test-first development

#180
I don't entirely concur, but I do think there's a real problem with areas that are hard to test. (As a web developer, I particularly run in to this with client side/browser side testing -- and yes, there are solutions, but they often have imperfections and annoying trade offs.)

I also think the benefits of testing have much more of a relationship to scale (both in terms of system usage/users, system complexity/size, development team size, etc.) and worst case failure risk that's often unacknowledged. (I don't suggest not having tests -- you'd regret that real quick. But I do think the appropriate level of test coverage can vary from project to project and component to component. Outer layers of onions probably matter, more, etc.)

Post reply on HN