10 ms·
Why Developers don’t TDD: a podcast series
Starting at episode 14 : https://agilenoir.biz/series/agile-thoughts/
- st3fan 8y agoHey. I do.
- mikekchar 8y agoHere's a question I find interesting, though: Do you TDD or do you write tests? Lots of people write tests for their code. I don't know many people who actively embrace the idea of TDD -- where the testing activity is driving the other aspects of their coding. Even among the people who do, I know of very few people who agree on what the word "driven" means. I suppose I should be more inclusive and say that "driven" might just mean, "I write tests". I've had numerous people tell me that it is improper when doing TDD to modify production code to suit your tests (which, for me is a really weird definition of the word "driven" ;-) ). If you do TDD, how do your tests drive your development and do you find that it is a concept that you are able to communicate to others easily? Disclaimer: I have not listened to the podcast, but the combination of the title and this comment was too thought provoking to let slip by :-) Now I'm quite excited to find some time to listen to the podcast!
- voodootrucker 8y agoWhat I've found most people do wrong is start with unit tests, which test implementation not deliverable, then realize after writing a bunch of code they did it wrong. I tend to write the acceptance test first. e.g. #1 If I'm writing a web app I write a selenium test "as a user, when I click the button, I see X". e.g. #2 If I'm writing a distributed database, I write a test "state should converge". These acceptance tests (aka end-to-end, UAT, UI test) ensure the desired end state is tested for, then I work outside-in to create implementation, writing unit tests as needed along the way. When I find people fail at TDD, it's usually due to the lack of knowledge, ability or infrastructure to approach the problem this way. Small stories in the correct order are also critical. I agree with the "risk first" approach an article on HN described yesterday. Source: I taught a course on TDD to some big enterprise clients.
- lancerkind 8y agoRegarding your first paragraph. It sounds like your mixing up the TDD workflow with ATDD. ATDD uses a requirements level view (macro test) and those concepts are usually well known before starting development. So you can write those tests upfront before development. TDD is about writing tests as you build the design. You’re not supposed to write a bunch of micro tests before writing any code. Rather you want to write a single micro test, then write a little code, when the test goes from red to green, you then enhance your existing test or add another test, then add a little more product code. So the effect is growing your tests as you grow your product code. Episode 12 illustrates this workflow for a simple example: https://agilenoir.biz/podcast/012-an-example-of-doing-tdd/ https://agilenoir.biz/podcast/012-an-example-of-doing-tdd/ The TDD series starts with episode 9 and is still continuing as of episode 15. https://agilenoir.biz/series/agile-thoughts/ https://agilenoir.biz/series/agile-thoughts/
- alkonaut 8y agoThe problem I find is that it takes quite a long time after having a sketch solution to realize that it’s a dead end. You start with “as a user when I press the X button...” but you realize there is no way a button will do. The premise is flawed. It has to be a multiselect list. And this can’t be a user thing, it has to be a config thing” and so on. That is: you can’t (no one could) even specify what is to be implemented without implementing one or more sketch solutions. You can specify the user problem but not the solution. “as a user I need to do X”. But a problem specification alone doesn’t allow easily creating a test on any level. If I were to do “TDD” I’d perhaps accept tests as being not the first step but the step before the final solution. Sketch solution(s). Throw away sketch. Tests. Final solution.
- mikekchar 8y ago> Sketch solution(s). Throw away sketch. Tests. Final solution. I think it's worth pointing out that this has been my interpretation of the general approach that XP originally took many years ago. If you know the general design that your story should take, you do a test first approach using your knowledge of what you are doing as a guide. However, if you don't have a good idea of the best approach to take, you "spike" a solution, throw away the code and then use test first to develop the "final" solution (hard to say "final solution" in XP, so I hope people understand what I'm saying here -- the solution that will be refactored over time as opposed to the solution that will be rewritten ;-) ). As the sibling thread pointed out, though, "test first" in the TDD sense is an iterative process and usually you write a test, satisfy it, write another test, etc, etc. You wouldn't want to write all your tests up front because it would constrain your design too much -- and then it wouldn't be "test driven", even if it is good ;-). I find it especially interesting that you use the word "sketch", which is exactly the same word I use. For me the activity is based around trying to get my head around the basic composition in the design. But like you say, if you are unsure about the UX workflow, just banging out some code and looking at it can make you realise, "That work flow is just not going to cut it because it doesn't use/generate the information I need".
- programmingyes 8y agoBecause it's tedious and not as fun as just going for it.
- lancerkind 8y ago:-) I actually enjoy writing well crafted code that does test and production functionality. Still, I admire your spirit. Just don’t join my team. ;-)
- programmingyes 8y agoGood idea. I'd take your code coverage down to single digits in one afternoon bam!
- Vanderson 8y agoCan someone recommend a podcast on TDD that is to the point? I couldn't get into these because they seem more entertainment focused than technically focused.
- lancerkind 8y agoThis is tough to do in a listening medium. Episode 12 covers a simple example that expresses the workflow and give you the general idea. https://agilenoir.biz/podcast/012-an-example-of-doing-tdd/ https://agilenoir.biz/podcast/012-an-example-of-doing-tdd/ Getting a copy of “TDD by Example” or buying a video course will get you further.
- marcinzm 8y agoBecause I find that I do not fully understand a problem and it’s potential solutions until I am working through it in reality.
- lgunsch 8y agoWhen Kent Beck (credited with helping create TDD) talks about TDD in his book, that is the primary reason for following TDD. He mentions, that if a developer already knows the solution, just do it. TDD is not helping at that point.
- elemeno 8y agoI used to have that view of the world as well, that a lot of the programming I was doing was simultaneously exploring the problem space as well as working towards a solution and thus writing tests (let alone full blown TDD) wouldn't work. I think that what changed my mind, other than the dubious joy of maintaining my own code a couple of years down the line, was the realisation that while I don't know the solution to the problem yet I do know what each function I'm writing is supposed to do and thats what I should be testing. As a side effect it also meant that the functions I was writing became smaller (easier to test) and it became easier to see what the end solution might look like because I could understand the intermediary steps more easily. Or to put it another way, I might not know how to write the compiler, say, but I do know that I'll need to start off by reading a line of input and I can test that I'm doing that properly, etc.
- voodootrucker 8y agoGood example: writing a compiler. I started (but never finished) writing a WASM interpreter in JavaScript. (https://github.com/bgard6977/wasm-int https://github.com/bgard6977/wasm-int) My test suite had simple programs in C, and used emcc to compile and run them, then compare the results from a known-good implementation to the one I was writing. As I went, I would add one new instruction to the program at a time. That's a perfect example of outside-in testing, and evolving the requirements, tests, and code simultaneously.
- 8y ago
- fgheorghe 8y agoEngineers are a rare thing among developers. Most are self taught and have no clue what they are doing, they just “do” stuff. They immitate what they see on stackoverflow or reinvent the wheel.
- gaius 8y agoTDD requires you to manually predict every possible failure mode and edge case before starting work. It is obviously complete nonsense. Pure snake oil designed to sell training and consulting, not to produce working software.
- tashoecraft 8y agoWhile I don't do TDD, I know this isn't correct. The idea isn't to prove every single possible way the code can go wrong. It's supposed to be an iterative process, this should do that small thing, write tests to prove it, then refactor updating your tests. Saying it's just designed to sell training and consulting is ridiculous.
- lancerkind 8y agoNicely said @voodootrucker. And I agree with @Tashoecraft. Lots of people get value from TDD. Unfortunately, some don’t and assume it’s the TDD process that’s broke. Its not the tool’s fault. It’s also understandably difficult (though not rational) that groups of people have trouble adopting new practices like TDD. Agile Thoughts podcast exposes some of the social blockages starting with episode 14: https://agilenoir.biz/series/agile-thoughts/ https://agilenoir.biz/series/agile-thoughts/
- voodootrucker 8y agoIt sounds like you have experienced a project where all the tests are defined up front? This generally should not be the case. The process should look more like: 1. write a test 2. make it pass 3. refactor 4. repeat Generally, one would start with "the happy path" tests, not spending too much time testing for all the failure cases until the correct functionality of the overall feature works as intended.
- dkarl 8y agoThe ideologies that developers publicly claim are often described as religions. One way they resemble religions is that people who espouse them don't live the way you would expect them to if they really believed in them.
- voodootrucker 8y agoXP (and by inference TDD) is often described this way. But after one has practiced it for a while, it's hard to go back. The way I describe it is this: When most people start as programmers, they write a big 1000 line file that should completely solve the problem. Then they run it, realize it was very wrong, and spend hours debugging it. As programmers learn, they tend to practice "error driven development": they get an idea what they want to happen, they run the program (usually "hello world" to start), and slowly run, edit, run, edit until it evolves into what they want to see. If you practice 2nd process above, you are one step away from TDD. You are still testing, you are just using manual tests. Once you learn to automate those tests easily, why wouldn't you TDD?
- lgunsch 8y agoI've done TDD for years now, and see how my peers do development (non-TDD), and I would definitely agree.
- goostavos 8y agoIs it at all possible that different people like different things, or maybe think differently, or perhaps find different workflows to be productive? If you could buy any of those as anything less than totally preposterous, then you may be able to make the next jump to considering why people like a development practice that differs from the one your prefer. I like tests as more of a 'checkpoint' thing, myself. To each their own. Also, I spend most of my time in a REPL, which I suppose is pretty close to what people tend to get from a TDD kind of loop.
- jacques_chester 8y ago> Is it at all possible that different people like different things, or maybe think differently, or perhaps find different workflows to be productive? Yes. But I don't think that's entirely down to innate or inborn characteristics, I think it mostly comes down to experiences. I tried to learn TDD from Beck's book and walked away thinking it was nonsense. Then I went to work at Pivotal Labs and I got a chance to learn it with people whose job consists largely of teaching it. Neither experience is about my largely inherited characteristics. They were experiences. Both were valid in themselves. I have experienced TDD in the good and the bad. I prefer the good, but I know why most folks consider it to be bullshit: that's how they've experienced it.
- Crazyontap 8y agoThis is a very good article on the same topic by DHH. A great read if you haven't read it before: > Test-first fundamentalism is like abstinence-only sex ed: An unrealistic, ineffective morality campaign for self-loathing and shaming. https://dhh.dk//2014/tdd-is-dead-long-live-testing.html https://dhh.dk//2014/tdd-is-dead-long-live-testing.html
- lancerkind 8y agoLol. Absitinence only sex Ed has nothing to do with TDD. Nor is it fundamentalism. It’s a waste of time to ponder as no real conclusions can be made from slapping the fundamentalism label on TDD. Better to just have an open mind and give it a go. And pay attention to the real benefits than to poison your mind against trying something that could help you deliver more features.
- Huggernaut 8y agoTo me this is confusing the level of abstraction tests sit with when the tests are written. You can write system tests first and you can write unit tests last, they are orthogonal. I practice double-loop TDD, which involves writing a system level test to drive out some behaviour, then writing other integration or unit tests down through the layers until the system test passes.
- lancerkind 8y agoNice! That’s is the best workflow for me too. Your basically working from big picture downward or said another way: outside in. To do so otherwise creates more risk. I feel the bottom up approach leaves me exposed to discover bad news later in the game and I have to go back and refactor or toss a bunch of code.
- michaelcampbell 8y agoThis is something I need to try. And concisely stated. Thanks.
- voodootrucker 8y agoI've heard this called "outside-in" testing.
- todd8 8y agoI've been a developer for many years, so most of the time I kind of know where I am going and have a map in my head guiding my development. I like test cases to help me with refactoring, but full TDD seems to slow me down when I try it. I have found that TDD helps quite a bit when coaching a new developer. It sets up intermediate goals that are not as daunting to get to. Sometimes thinking about a big project can just seem overwhelming to someone that hasn't done it before.
- lancerkind 8y agoI like your points about when working with a new developer and how it creates intermediate goals. Are you Pair programming when doing this?
- todd8 8y agoSometimes, but more often just looking over other people's work or progress when I'm asked for help or advice.
- deleted 8y ago[deleted]
- LandR 8y agoTdd won't take off until developers realise they need to start thinking more. If you don't understand the problem you're trying to solve well enough to write tests, you shouldn't start coding. But too many developers just want to dive in and hack code together and try to figure it out as they go. The resultant code from this is almost always a tire fire. Someone on hn a whole ago posted the quote "coding should be to software development what moving the pieces is to playing chess" I couldn't agree more. I wish more developers would get this.
- war1025 8y agoI don't do TDD because for the types of code I generally write, it is much easier to test the general cases back running the code directly. It's not that I don't have tests in mind when writing the code, it's that the tests I am working against are behavior driven, so it is easiest to just perform the actions myself and see where it falls down. Particularly in UI code, TDD seems to lead to code that is "technically correct", but produces a UI that is an absolute pain in the ass to do anything with. Tests have their place, but the proper time in the dev process to write them is very much a personal preference thing and nothing more.
- querulous 8y agomy experience is the exact opposite. ui code is where tdd shines the most because your spec is almost always 'when a user presses this button/fills this form/navigates to this page of the app do this thing'. there's zero uncertainty in the expected behavior so you can start out by writing exactly that test
- war1025 8y agoWhich is what I mean by leading you to "technically correct" code. At the end of it, you have everything wired up in a way that exposes the functionality, but you haven't necessarily spent any time testing out the ergonomics of actually using the UI. Could just be the people I've worked with aren't good at UI design.
- haolez 8y agoWhat about languages with strong typing? Is it as useful as with, let’s say, Ruby?
- voodootrucker 8y agoIt's 100% as useful, but much more difficult to mock and inject.
- lancerkind 8y agoThe static typing makes mocking harder (Java, C#). Working in Javascript makes mocking so easy you don’t need a mocking framework. TDD is an awesome practice in all languages, strongly types or not.
- paulddraper 8y ago> much more difficult to mock and inject Isn't it just the opposite? The whole reason of Mokito ( https://site.mockito.org/ https://site.mockito.org/ ) is to make Java mocks easier by adding dynamic typing.
- jacques_chester 8y agoWhat you write in your tests, how you test, how you design the software and so on are altered by the language you work in. This is as it should be. If I have a type system that prevents certain classes of defects, I gleefully accept that bounty. If I have a type system that simplifies certain classes of tests, I gleefully accept that bounty. I will happily rant and complain about all of them, but I will also try to program to the strengths of what I'm using. Wishing one language was a different language is a waste of everyone's time.
- pooya72 8y agoThis is a nice series, but the background music is too loud.
- rongenre 8y agoUsually it's because we let TDD lapse, and suddenly the rebuilding the scaffolding to properly do TDD for a feature is more work than the feature itself.
- jacques_chester 8y agoTDD (I lump together lots of extended practices here) is hard. It's hard to learn from a book or blog post. It's often hard to solve the many problems of "how do we test <behaviour X>?". It's hard to know when to stop spiking and start test-driving. It's hard to stick to it when you solo and you think "oh I can just skip a few steps here and come back afterwards". It's hard to learn mockist style and statist style. Hard to go all-in on one style, then all-in on the other style, and then afterwards often hard to strike the right balance between them. It's hard to deal with the vast universe of technologies which, having not been developed in a TDD fashion, are hard to test. It's also hard being told your years of practicing amongst practitioners aren't real experiences. That you didn't see the remarkable speed and confidence it granted on massive codebases with hundreds of engineers in dozens of teams working for multiple companies on several continents for years on end.
- rickdg 8y agoBecause tests have to match requirements and those are usually ambiguous or close to non-existent.
- SomeHacker44 8y agoBecause I test everything thoroughly at the REPL as I am developing, and record my REPL tests. Because I have been doing this for 35+ years and generally have acceptably low error rates without it. Because I would rather invest test resources in runners that actually exercise the application at the UI layers and the API layers directly in a fully configured and deployed environment rather than trust mocked up unit tests. (Which CI can also do.) Because tests can have as many bugs as the underlying code. But, for teams of junior developers, I am all for it. (I also will write some test harnesses/unit tests for aggressive or major refactorings.)
- pjmlp 8y agoMy fun test for TDD advocates is picking random GUI framework X and ask the presenter how to TDD a native GUI. After all I am not supposed to show anything on the screen, send a shader to the GPU, or change any widget property without an existing test.
- rgoulter 8y agoAFAIU TDD, it's beneficial to have an automated test than can check what I'd check manually if I didn't have automated tests (since automated checking is quicker, and is consistent). One benefit of writing a test before fixing code is it avoids the problem of writing a test which passes but doesn't actually check the broken thing. ("You have to write the test before or else you're doing it wrong" seems overzealous or cargo-culting to me). Of course, as with anything, "it depends" and so if you're confident that adding more tests would hinder your development more than benefit it, sure. Some programming tasks are difficult to get the system setup for test input, or for checking test output. But it's not like you're not going to check whether the program works, and so it seems beneficial to make an automated test if you can.
- pjmlp 8y agoI fully support automatic testing as far as possible. Now TDD cargo culting of writing tests before working code, or even actual design of data structures just seems nonsense to me. It only works for CLI demos of simple tools, or data processing pipelines. Anything else seems convoluted, without a sound architecture design, and just impossible in some scenarios, e.g. GUI code, UI/UX. Tests should be a mix of unit, module and integration tests, written after the architecture design, overall UI/UX design process, performance analysis if the chosen data structures are the best ones for the case at hand.
- Huggernaut 8y agoGiven that there are plenty of test harnesses that allow for testing of GUIs, what about GUIs do you think proves impossible for the TDD process?
- wolco 8y agoTdd is writing tests and getting a side effect of production code. Tdd feels like you are always after the next hit. Turn that red into green by hardcoding. All that matters is green.
- salawat 8y agoI know when I'm coding for me I don't because to me, tests don't solve the problem I'm out to solve at the time. I want this thing, over there. A test does not get it there. Now, once I'm done with getting that over there, then I look at it and evaluate my level of testing I'm going to commit to it. Some code, I can keep straightforward and narrative enough where even coming back a year later, I can pick it up and quickly move with it. Part of my secret to doing that is forcing myself to sit down with a saintly non-programmer, and talk them through it. If I can get them to follow, I've got it nailed down. If I can't, I haven't whittled it down to it's simplest incarnation. For all the other code... Let the test suites be written!
- segmondy 8y agoTDD wasn't a thing when I started coding, there's no software that I use or that has been influential to me that's developed using TDD. For my personal projects, I'll never use TDD, it's a crutch, I don't even jump into tests, I add assertions and then only add a test if I find a bug that wasn't obvious.
- schneiderscode 8y agoUsing a directory watcher to rerun ruby unit tests on file changes was something that helped me do more TDD. Having a terminal open and seeing it turn from red to green as tests start to pass on every save is a very satisfying feeling. Saving and manually re-running your tests after changing what should make the next test pass is not. Edit: It was guard for those curious: https://github.com/guard/guard-rspec https://github.com/guard/guard-rspec
- theptip 8y agoThere was a back-and-forth between DHH and some of the original TDD advocates a while ago, which I thought was pretty interesting. Test-Induced Design Damage: https://dhh.dk//2014/test-induced-design-damage.html https://dhh.dk//2014/test-induced-design-damage.html And a resulting conversation between Kent Beck, Martin Fowler, and David Heinemeier Hansson: https://martinfowler.com/articles/is-tdd-dead/ https://martinfowler.com/articles/is-tdd-dead/ I think a lot can be learned from the exchange.
- foxyv 8y agoTDD is great when you have a solid set of requirements. But when you are doing "Agile" and the requirements change every day, your tests can be invalidated almost instantly. If I was doing a reliability focused project TDD would be my first step. But that isn't the kind of project I work on.