TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Is TDD dead?

84 点作者 shutton将近 11 年前

25 条评论

phpnode将近 11 年前
TDD is not dead, but hopefully the practise of foisting rigid, prescriptive, quasi-religious software development methodologies on creative individuals is.<p>TDD, like all of these things - eXtreme Programming, agile, has good points and bad. Listen to what these people have to say, and then take what works best for you.<p>To me, TDD is about writing my code and my tests at the same time, not test first. As soon as I write just enough code to do something, I&#x27;ll write a test to see if it actually works. I&#x27;ll then expand on that test and perhaps add a few more as I refactor that piece of code.<p>This means I still get the benefits of exploratory programming, unconstrained by test first, but I also get the security of knowing that my changes didn&#x27;t break anything. It feels very natural to develop this way, as the code base grows, your confidence in its quality grows with it, rather than the inverse (lots of passing tests). Also a fast test suite which runs on file save is <i>addictive</i>, I cannot imagine returning to F5 Driven Development now.
评论 #7859058 未加载
评论 #7860888 未加载
tunesmith将近 11 年前
The embedded debate about &quot;hexagonal&quot; architecture is unfortunate.<p>I think one of the very common sticking points about refactoring and testability is that when trying to demonstrate techniques, you have to pick simple examples to isolate the techniques.<p>When in reality, those simple examples don&#x27;t <i>need</i> those levels of abstraction or indirection. DHH&#x27;s gist is a perfect example of demonstrating something that - by itself - doesn&#x27;t need to be refactored in that manner.<p>But it completely misses the point. Those refactoring techniques are essential for when your codebase is 100 or 1000 times more complex. (Jim W. mentions this explicitly in his youtube video.) But the problem is you&#x27;d never show that complex a codebase in a demonstration, because the mental load in understanding the prerequisites (before getting to the actual refactoring) is too large.<p>I think another common sticking point is that people talk about refactoring to make a codebase more testable. And that is a worthy aim and all, but making it more testable isn&#x27;t the end goal. Making it more testable forces you to separate your concerns&#x2F;layers, and <i>that&#x27;s</i> the goal. The reason that is the goal is because as your code grows, you still want the product to be easily changeable so it can be quickly responsive to customer&#x27;s needs. And if you need to switch out your data repository implementation on short notice due to your site being suddenly popular, that&#x27;ll be easier&#x2F;faster if that implementation is separated out.
评论 #7860658 未加载
andymatuschak将近 11 年前
I really enjoyed Gary Bernhardt&#x27;s response to this discussion: <a href="https://www.destroyallsoftware.com/blog/2014/test-isolation-is-about-avoiding-mocks" rel="nofollow">https:&#x2F;&#x2F;www.destroyallsoftware.com&#x2F;blog&#x2F;2014&#x2F;test-isolation-...</a><p>You should read the whole article, but to motivate:<p>&gt; This post was triggered by Kent&#x27;s comment about triply-nested mocks. I doubt that he intended to claim that mocking three levels deep is inherent to, or even common in, isolated testing. However, many others have proposed exactly that straw man argument. That argument misrepresents isolated testing to discredit it; it presents deep mocks, which are to be avoided in isolated testing, as being fundamental to it; it&#x27;s fallacious. It&#x27;s at the root of the claim that mocking inherently makes tests fragile and refactoring difficult. That&#x27;s very true of deep mocks, but not very true of mock-based isolation done well, and certainly isn&#x27;t true of isolation done without mocks.<p>&gt; In a very real sense, isolated testing done test-first exposes design mistakes before they&#x27;re made. It translates coupling distributed throughout the module into mock setup centralized in the test, and it does that before the coupling is even written down. With practice, that preemptive design feedback becomes internalized in the programmer, granting some of the benefit even when not writing tests.
zwieback将近 11 年前
Inside DHH&#x27;s arguments is also a general argument against what I call frameworkitis - the desire to overgeneralize an application in the vague hope that the code will get used in a different way in the future. In my middle career I was prone to that but in the last 5 years or so I&#x27;ve been trying to resist that impulse. I now try to write the application and if another similar application comes around I might pull out reusable portions. On the whole this approach has been a win for me.<p>Not that Beck or Fowler are advocating anything different but I think DHH is the one with his finger on the pulse of current development trends.
评论 #7858812 未加载
评论 #7859257 未加载
politician将近 11 年前
It seems like there is a general realization is that TDD is useful for increasingly narrow contexts to create business logic where there already exists a generally accepted architecture.<p>In other words, the controllers of typical web apps which AFAICT is where the technique originated and the source for a lot of the introductory examples.<p>It&#x27;s not a silver bullet, but what is?
评论 #7858365 未加载
评论 #7858182 未加载
评论 #7858949 未加载
shutton将近 11 年前
Some interesting conversations between DHH, Kent Beck and Martin Fowler.<p>DHH can be quite outspoken at times but I think he&#x27;s right to have this discussion and to have it in public so we can all learn something.
评论 #7858438 未加载
tunesmith将近 11 年前
I&#x27;m interested in how Martin and Ken say they don&#x27;t actually use a lot of mocking.<p>Let&#x27;s say you have production code where A will call B, and B will call C. Basic layer separation. It might be a controller calling a service method, which calls a dao.<p>If you want to test B, then in my mind, that means you want to write a test that would call B (similar to how A does). And then since you don&#x27;t want C confusing things, you&#x27;d create a mock of C (returning a canned result), and assign it to B.<p>So... how would you test B without mocking C? Are Martin and Ken simply content to let B call C, which would imply that it is an integration test rather than a unit test? Or is there some other design technique they&#x27;re using?
评论 #7860698 未加载
aikah将近 11 年前
In my opinion,this debate has a lot to do with the language used,the tools ,the IDE...<p>Java&#x2F;C#&#x2F;... can be heavily assisted with the right IDE,(test suit generation,mock&#x2F;stub generation...).So the cost of testing can be light,no matter how big the codebase is.<p>In JS,or ruby.One actually has to write everything. Therefore,one would be less tempted to write heavily decoupled code with a huge graph of function constructors&#x2F;classes. While ruby has a lot of sugar for a wide range of things,that&#x27;s not javascript case.<p>So in my opinion,the cost of testing and managing test suits is higher in languages such as javascript or ruby,therefore one is tempted to write as little code as possible,and sacrifice decoupling and sometime testability.<p>In one hangout,DHH comes with a snippet of code,highly decoupled and testable.But does ruby encourage this kind of architecture?because it&#x27;s more code to test and more testsuit to manage(and more tests to rewrite when refactoring).<p>So isnt it more a language &#x2F;tooling question than a TDD&#x2F;mock not TDD&#x2F;mock question?
kragen将近 11 年前
I&#x27;d really like to hear what Hansson, Fowler, and Beck have to say, but not so much that I&#x27;m willing to sit through videos. The summaries are good (if you click the &quot;more...&quot; links) but I&#x27;d really like to read transcripts. Are there transcripts?
shawnps将近 11 年前
I once talked to someone from GitHub who said that the way he sells people on TDD is to show them the tests running automatically when they save a file. I thought this was a pretty neat idea, and have used it on a couple of projects. If you write Go for example, you can run fswatch . &quot;clear &amp;&amp; go test&quot; in your project&#x27;s folder and get this result.
评论 #7858796 未加载
jamieb将近 11 年前
&quot;TDD creates bad architecture&quot;.<p>What is good architecture? I subscribe to the idea that we are doing software engineering and as such there are some &quot;generally&quot; understood principles such as SOLID, the Law of Demeter, Cyclomatic Complexity, etc that provide objective measures of &quot;good&quot; architecture (I apply SOLID all the way up the architecture hierarchy not just on classes).<p>What I&#x27;ve noticed is that TDD results in code that scores well against these measures, while code that scores well is easy to test (i.e. after writing the code).<p>Therefore, I think the argument that TDD creates bad architecture is false.<p>About 25 minutes into the talk we get to the crux of DHH&#x27;s complaint and it is that Hexagon is an alternative to the Active Record (which he created) and the only reason Hexagon exists is to allow TDD. Hexagon requires throwing away the really useful code that is Active Record.<p>Hexagon appears to be an attempt to introduce sound software engineering practices (SOLID etc) into the Ruby world (with what success I do not know). Active Record and Rails in general is really useful if what you want is what it does, but sometimes its not. The implied claim that Hexagon is a bad architecture is false. The claim that Hexagon only exists to facilitate TDD is false.<p>&quot;Mocks returning mocks returning mocks&quot;<p>I use mocks. Fowler and Beck said on the whole they don&#x27;t use them which genuinely surprised me. They cited examples of code where the test actually enforced implementation rather than purpose. I think that&#x27;s probably how I wrote tests for the first few years. Code that results in mocks returning mocks returning mocks is code that is violating the Law of Demeter. Its bad code. It happens to be really hard to test, and it happens to be <i>really</i> hard to write tests first that way. Universally I&#x27;ve only ever seen tests like that when the tests were written after the code. TDD doesn&#x27;t produce code like that because its easier to refactor it rather than keep digging that hole.<p>Mocks returning mocks returning mocks is a symptom of <i>not</i> doing TDD.<p>&quot;My mind works differently... I have to write code first&quot;<p>Spike. Problems that I don&#x27;t know how to solve I spike first (I write code with no tests, or with tests only as drivers of execution). That&#x27;s easy. The hard question is, &quot;Now I have all this code, I have to throw it away and TDD it?&quot; That&#x27;s pretty hard to stick to in a business environment. I choose to write tests-after for all those pieces of code that <i>already</i> meet SOLID metrics, and rewrite the code (using TDD) for the pieces that don&#x27;t. The pieces that don&#x27;t are very difficult to write tests for after, and they also happen to be the pieces where I find bugs (for example, I&#x27;ll cut and paste a bit of logic and find its wrong for one set of inputs).<p>&quot;All code should have full coverage of automated tests&quot;<p>All three agreed that this is the case. Fowler: &quot;If you have a full suite of tests I don&#x27;t care how you got it [TDD or not]&quot;. I don&#x27;t know about you but I&#x27;m still fighting this battle. I also have to deal with teams that have a &quot;full suite of tests&quot; and 80% test coverage, but where every single one of those tests simply executes code. No actual &quot;test&quot; occurs. Indeed, in particularly memorable test, I managed to delete 70% of the lines of code and all the tests passed (including deleting the one line that was the main purpose of the method). Approximately 90% of all the tests were complete garbage: they reported success as long as the code didn&#x27;t throw an exception.
评论 #7859231 未加载
评论 #7859111 未加载
评论 #7862195 未加载
评论 #7859201 未加载
n1ghtmare_将近 11 年前
This is a strange debate these days. For me TDD made me a much better programmer. I&#x27;m not sure how I used to work without it. It saved me on many occasions. It does lead to better quality (from my experience). Frankly I don&#x27;t see a single downside. Seriously.<p>Is it hard ? Sure.
评论 #7858609 未加载
suckprogrammer将近 11 年前
Coming from the furthest thing considered open-source - all we have are TDD evangelists - we have 0 implementations. The one die hard TDD I&#x27;ve seen is so unproductive it&#x27;s painful to the business. Is this just something that&#x27;s enjoyable to kick around?
crazytony将近 11 年前
I don&#x27;t know that gist just seems contrived. I&#x27;m totally not a rails guy so I have to ask: is that the only way you can implement that in rails land?<p>In (most)JS and&#x2F;or python I would just monkey patch the save method and&#x2F;or constructor on the employee object to get the isolation and branch coverage.<p>I would probably need to do some of the same crazy abstraction for Java though.
评论 #7858549 未加载
评论 #7858547 未加载
zinxq将近 11 年前
Much like Agile, there&#x27;s good concepts in there but it seemed particularly prone to people taking things to far too far. (maybe you could even use the word &quot;too extreme&quot;)<p>Guice is a representative programmatic example. Reasonable idea but once you trickle it into your code, it becomes a cancer quite quickly.
jedp将近 11 年前
I clicked on this article thinking it was about Telecommunications Devices for the Deaf, wondering what the alternatives are now that installed payphones with TDD consoles are not to be seen anywhere. I must look into the smart- and feature-phone alternatives.
andywood将近 11 年前
Nope. I know people who are still using it.<p>I believe it comes down to the team. Who is on it, how the team works together. If there are a lot of people on the team who enjoy working that way, they&#x27;ll use it. If not, they don&#x27;t. It lives on.
progx将近 11 年前
If TDD is the best thing on this planet, why have we to discuss about it? Why did not everybody use it?<p>Answer: obviously, it is not the best thing on this planet.<p>Like &quot;use the right tool to solve a problem&quot;, use TDD if it solves a problem.
评论 #7858103 未加载
评论 #7858152 未加载
评论 #7858064 未加载
评论 #7858324 未加载
ing33k将近 11 年前
Don&#x27;t miss this part of the video. <a href="http://www.youtube.com/watch?v=JoTB2mcjU7w&amp;t=29m20s" rel="nofollow">http:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=JoTB2mcjU7w&amp;t=29m20s</a>
markrages将近 11 年前
&quot;living&quot; vs. &quot;dead&quot; seems like the wrong dichotomy to me.<p>How about dialing back the religiosity and ask &quot;is TDD useful?&quot;
programminggeek将近 11 年前
One reason Ruby makes it needlessly difficult to do do great software architecture and sane TDD is the lack of contracts or strong parameters.<p>It is easy to take for granted that when you have a function like this:<p>function foo(int x, string y) { int count = x * 100; print y + &quot; &quot; + count.to_string(); }<p>...that if you send in a string for x or an int for y the function will blow up. And if you are using a compiled language, it will yell at you before you even attempt to run the code.<p>In ruby the equivalent code would run just fine, even with generally bad input and it is totally up to you (the programmer) to police yourself to write code that doesn&#x27;t send across bad data.<p>A ruby programmer (and probably the same goes for PHP and Python), will end up writing a fair amount of tests that simply ensure that the boundaries are enforced properly and sanely in the code.<p>There is a lot of love about ruby, but if you are going to write safe, dependable, bug free code it is up to the programmer to enforce boundaries, do validations, and so on and so forth and then write tests that validate that they are still correct over time.<p>Part of the reason this argument isn&#x27;t so much happening in other languages is in part that there is maybe not as strong of a culture of TDD in other languages, but also simply because some of the problems don&#x27;t exist in Java, Scala, C#, etc. because of a type checking compiler and stronger boundaries between components.<p>A lot of the things that we consider &quot;good architecture&quot; are simply the way we name things, the way we put files in folders, and where we place boundaries in our code. We could write everything as a single file that ran sequentially and jumped to different locations (which is largely what happens anyway), but to make things reasonable and understandable we use patterns like MVC, or composition based functional programming, or MVVM, or various OOP patterns, and so on to express program logic and create logical, sensible boundaries in our code.<p>If you see the world through the lens of naming things, file structure, and conceptual boundaries, you will see this argument about TDD is more about how strong the boundaries in our code should be and where they should live, not whether TDD as a tool is a good thing or a bad thing.<p>Rails MVC sees the world as 3 tightly coupled things - model, view, controller. And in that tightly coupled world(along with weak ruby boundaries), TDD is painful and probably not worth your time. DHH is right about that 100%.<p>If you don&#x27;t structure your project as Rails MVC does, TDD can be a very pleasant way to build your project and have confidence as you change it over time. Ruby is not the best tool for that job, but it can be made to work. In general, the weaknesses of ruby&#x27;s boundaries will mean this argument will keep coming up over time and will never be solved.
fireWalker将近 11 年前
TDD is good. I think &quot;Test-First&quot; is dead. Few places I&#x27;ve been at have been able to do test-first.<p>Small groups trying to deliver on aggressive schedules waste too much time with test-first.<p>Having a competent leader and skilled team that can follow SOLID principles removes the need to be test-first.<p>TDD is not dead. Test-first probably is.
评论 #7858238 未加载
评论 #7858225 未加载
评论 #7858224 未加载
评论 #7858802 未加载
评论 #7858237 未加载
compsci_mofo将近 11 年前
Is TDD dead? No, it just smells that way. Like all cargo cults, only the clueless follow it religiously. You can spot them a mile off - with a book they bought off of pragprog, their whole test before breakfast mantra, and usually by their crappy brittle test forged code.
andyl将近 11 年前
In my experience, if you are a competent TDD practitioner, you have a leg-up on those who are not. Sometimes a big leg up.<p>Yeah, it takes a long time to become competent.
moepstar将近 11 年前
Betteridge says No