3 ms·
> I think TDD is an abomination I'm intrigued. TDD may bring way more pomp and circumstance than it deserves, but when you get right down to it all it says is:
by randomdata 3y ago
> I think TDD is an abomination
I'm intrigued. TDD may bring way more pomp and circumstance than it deserves, but when you get right down to it all it says is:
1. Write a test first so that its failure state is proven.
2. Test behaviour, not implementation.
I have certainly been caught in haste writing a test after the fact, messing it up – in a way that saw it pass, and then later realized that it wasn't actually testing anything. #1 solves a real problem.
Which must mean the abomination is the behaviour testing? Do you really care about the implementation, though? Surely that can be considered throwaway? You are not going to gain anything asserting that you used bubble sort and have that assertion fail when you update your code to use quick sort.
- jdlshore 3y ago3. Work in very small steps (a handful of lines of code) and incrementally build up as you go.
- randomdata 3y agoIs that not just the outcome of #1? Short of trying to capture many different things in a singe test, which then becomes a nightmare for future readers, a single test just isn't going to touch that many lines of code and if you get ahead of the tests by doing more while you're in there then you're back to the problem #1 tries to solve.
- jdlshore 3y agoIn theory, it’s the outcome of #1; in practice, it’s a nuance many people miss.
- nikitaga 3y ago(not the OP, just my two cents) (1) is the distinguishing characteristic of TDD, but it is not an end in itself, it's a mere way to achieve (2). You write the test after you have the API design, but before you have the implementation, and thus supposedly decouple your test from the implementation, since you don't have the implementation yet. This approach never sat right with me. * It makes design iteration more costly: if you want to change the API design as you're implementing the thing, now you have to change a bunch of tests to use the new API, and that's when you don't even have the implementation to test yet! This makes you subconsciously prefer quick and dirty design patches instead of making bigger but better changes to the design. So you're statistically trading potentially better design for potentially better tests. I'd rather have the former than the latter, because it's much more insidious. * Just like TDD encourages writing tests for behavior instead of implementation, it also encourages relying on tests as the sole arbiter of code correctness. The supposed better quality of tests is offset by over-reliance on them, including by not adding tests to check the weak points of your implementation (because you already wrote all the necessary tests before you came up with it... right?). I've worked with some TDD-loving developers who didn't even feel the need to run the code they wrote on their dev box, in the application context. Tests pass, therefore straight to production. The bugs caused by this attitude offset all other advantages of TDD. * TDD pretty much relies on 100% unit test coverage, because since you (supposedly) don't think about what the implementation will be, you don't know in which methods the bugs are likely to be. This causes you to over-invest in writing unit tests, but writing and maintaining tests is not free. The risk of bugs is not the same in all of the code, and same for the cost of bugs. Not to mention that some of the code is better tested at a higher level with integration tests or end to end tests, but IME nobody takes TDD there, probably because it's too annoying. * Overall, TDD seems like an overly elaborate way to proactively "gotcha" yourself with various unhappy-path edge cases before even thinking about the implementation – thinking that would, in fact, expose more of such edge cases. I find that instead of this weird backwards overhead-heavy process, the usual development process works just fine. Start with the big picture, and leave messing with small details for last. Whereas TDD requires you to bring up all the small details / edge cases upfront (otherwise it's indifferent from regular testing). Like with most ideologies, there are some good high level principles to take away from TDD, but at the end of the day, most ideologies like this are designed to replace unreliable thinking with reliable process. And while that process may indeed reliably produce some kind of consistent output, it's not necessarily better than what you'd have without this process, or with a different process.
- pkolaczk 3y ago> 1. Write a test first so that its failure state is proven. This is useful for to me only when fixing existing code but not when writing new code. Before I write the implementation, it is obvious the test would fail. By not having to code the test first, I have more flexibility on changing the API if needed.