TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Lean Testing or Why Unit Tests Are Worse Than You Think

199 pointsby saranshkalmost 7 years ago

41 comments

guygurarialmost 7 years ago
The article makes some fair points for performing end-to-end tests. There is however a benefit of unit tests over end-to-end tests that is not mentioned: code locality. The cost of fixing a discovered bug seems to grow exponentially with the amount of code in which the bug may appear. Unit tests typically cover a small part of the code. If a unit test fails, isolating and fixing the bug is typically cheap. On the other hand, if an end-to-end test fails (due to the same bug) then isolating and fixing the bug can be quite costly because there are many different parts of the code that need to be checked. To me, code locality is the main advantage of writing unit tests.<p>At the end of the day, there is a spectrum of tests going from unit tests to end-to-end tests. The spectrum represents several trade-offs such code locality vs. coverage. In my experience, the most economical approach is to write a balanced mix of tests the lie along this spectrum.
评论 #17539870 未加载
评论 #17540501 未加载
评论 #17539880 未加载
评论 #17539861 未加载
评论 #17542122 未加载
评论 #17543231 未加载
评论 #17552319 未加载
评论 #17540710 未加载
paulmdalmost 7 years ago
Integration testing and unit testing aren&#x27;t direct substitutes. You would never ever say &quot;I have unit tests, I don&#x27;t need to run the product before shipping it&quot;. Furthermore, automated integration testing is strictly less capable than a human doing integration testing.<p>Unit tests also have the advantage of being cheap to set up and cheap to run, so their limitations in whole-system testing are offset by the fact that you can have many, many more of them. You can easily blow through a couple thousand unit tests in a matter of 10 minutes or less, whereas even a modest battery of integration testing will be an overnight process at best. That means your OODA loop is a lot faster on unit testing.<p>(the ideal is of course structuring your application so you can deploy many tests in parallel, but that&#x27;s not always possible.)<p>Fixing Selenium so WebDriver instances don&#x27;t take 60+ seconds to launch would be a major help. Until then, integration tests that work at a controller level (minus the UI) are probably the best compromise between speed and integration. You can pass in a mocked request as input, and assert on the output. Runs much faster than a &quot;true&quot; integration test with a driven browser client, but hits the whole stack better than a unit test. They are also really easy to set up, since you can just have a tester or an integration test go through the motions and then dump request data to JSON, then feed it back as a test. The lack of state persisted between requests makes implementation a lot simpler.
评论 #17541891 未加载
pshiralialmost 7 years ago
I find this article misleading; with a biased PoV. The author says &quot;empirical evidence is missing&quot;, yet advocates a testing methodology, banking largely on articles and PoVs of other individuals. Is there any software project the author would like to quote as a case-study? Is there <i>any</i> evidence to prove that the Lean method is <i>better</i> OR, the definition of <i>what is better?</i><p>It is OK to be economical in what one would see as a cost of testing a product end-to-end. Call it whatever term you like, but functionally testing a product end-to-end has always followed an <i>economical</i> approach, as all such testing is a factor of time &amp; resources. You&#x27;d perhaps be less economical if you were testing life-safety systems, but you could choose to be more economical if you considered your software to be not-that-critical, or, you needn&#x27;t have to set exceptionally high standards.<p>I find it extremely odd that unittests are even considered into this equation of &#x27;testing-costs&#x27;, despite decades of improvements in software development processes. Unittests should be part of &#x27;core&#x27; engineering &amp; a part of development. Not a task that&#x27;s added to testing costs. If you aren&#x27;t writing unittests (irrespective of whether its TDD or not), you are not developing&#x2F;engineering your product right. You are only building a stack of cards _hoping_ that it wouldn&#x27;t collapse at some point in the future.<p>It&#x27;s a sad state of affairs if one gives code 1st level treatment, but treats unittests, documentation, build scripts and other support infra as something less important; worth economizing. This is really what _matters_ when it comes to overall quality of a software.<p>One must remember that software is always improved, refactored, expanded, ported or worked on in some way or another. When unittests are missing, then the very boundaries that were meant to dictate the rules of the software don&#x27;t apply anymore. This leads to human errors causing portions of software to break.<p>Critical pieces of software that exist today, exist strongly because they were engineered right (Linux kernel for example). Not because their developers followed an _economical_ approach to testing. If an OS disto claimed to perform economical end-to-end testing (of a potential user&#x27;s most commonly performed paths), would the author of this article want to use that OS over one that has had strong ground-up unittests and testing of interfaces where they matter?
评论 #17540431 未加载
ciesalmost 7 years ago
Interesting article.<p>I&#x27;m a big fan of &quot;economic testing&quot;. Test that are not going to &quot;be economically viable&quot; to write during the dev&#x27;t of new software, usually do not get my permission to be written in that phase.<p>Unit test thus get written for part that we absolutely want to be maximum certain of that it works correctly. Mostly that functionality can be extracted into a library. For instance a lib that deal with scheduling of events of arbitrary length: we do not want to have issues with those getting messed up, so we try to get 100% unit test coverage of the functionality in that lib.<p>Another thing with unit test is that I found they mean something different in dynamic languages than in strongly typed languages. In the first unit test are often something to provide confidence that the type system can give you in the latter. Sure both will also test the logic. But this understanding has pushed me to love strong types (as a rubyist), as I can go with less unit test and still be more confident about my code base when it is being heavily worked on. Refactoring becomes so much easier with strong types, as all is &quot;in the code&quot;.<p>When it comes to integration tests I usually want to make a biz case for them. How much does it cost to have it all manually tested, and how much do the automatic integration tests cost to make. While including the benefit of being able to run the automated integration tests at near zero cost (thus several times per day if we need to).
评论 #17540536 未加载
评论 #17539939 未加载
sverhagenalmost 7 years ago
There&#x27;s two things that humble me on a daily basis, in no particular order: collaboration and testing.<p>While I use all sorts of testing, I still write a good amount of unit tests. For whatever kind of tests I write: not a day goes by without tests or the act of writing them exposing bugs that would otherwise have moved on to the &quot;next level&quot;. Doesn&#x27;t mean they&#x27;d have ended up in production, but they&#x27;d still have been a lot more expensive to fix.
lucisferrealmost 7 years ago
I kind of lost it at this point:<p>&gt; Kent C. Dodds claims that integration tests provide the best balance of cost, speed and confidence. I subscribe to that claim. We don’t have empirical evidence showing that this is actually true<p>And<p>&gt; There is the claim that making your code unit-testable will improve its quality. Many arguments and some empirical evidence in favor of that claim exist<p>Why rely on evidence when conjecture an opinion are so much easier?<p>So here&#x27;s my own limited evidence to toss on the other pile. Our team has started to unit test everything, 100% coverage. We don&#x27;t take this approach to testing lightly, it is a holistic approach that includes the code itself, focusing on architectures that enable testing and testability. Doing so has vastly improved code quality in measurable ways.<p>Code reviews are faster and easier as a starting point. It is easier for another person to understand quickly what each component does and what it is expected to do. Code is composed using small autonomous functional components that are uncompleted and easy to reason about and test. These make debugging easier because they can be isolated to simple components and tests. Bug fixes are faster to implement and test since the test infrastructure is already in place and does not need to be remediated in later.<p>Yes, we do also write integration tests. They tests the end-to-end scenarios we are designing the system to support. But unit testing is still the primary approach to how we design, while integration provides support by verifying complete scenarios.<p>However our approach admittedly doesn&#x27;t have &quot;Lean&quot; in the name, so that&#x27;s one downside I guess.
评论 #17544568 未加载
rectangalmost 7 years ago
Meh. Thinking about ROI when writing tests is important, but my analysis of ROI is mostly at odds with this anti-unit-test screed: the greatest ROI comes from writing thorough unit tests against <i>stable</i> low-level sub-components.<p>Integration tests, in contrast, require attention more frequently -- because not all subcomponents are stable and when one changes, multiple integration tests need superficial readjustment.<p>I&#x27;m skeptical that my own ROI analysis is more &quot;right&quot; -- it probably varies by project and team. The conclusion I draw instead is that ROI analysis is important in general when writing tests, but that one particular ROI analysis is unlikely to apply universally.
crazygringoalmost 7 years ago
Unit tests also help ensure both the coder and readers understand what the function&#x27;s defined behavior is supposed to be, 100%. They help with clear thinking to ensure you write the code correctly in the first place.
drakonkaalmost 7 years ago
There is an interesting article which responds to this and mentions some misinterpretations of references: <a href="https:&#x2F;&#x2F;www.tedmyoung.com&#x2F;looking-at-tdd-an-academic-survey&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.tedmyoung.com&#x2F;looking-at-tdd-an-academic-survey&#x2F;</a>
评论 #17540135 未加载
dalorealmost 7 years ago
This is making the assumption that writing tests takes longer to produce code then test without. But it has been shown that TDD can and usually does produce code faster with it. TDD makes you write code that&#x27;s easier to test, the tests are fast (mere ms). And it gives you confidence in your code, plus locality as you know the error since the tests either pass or fail each step.<p>Not advocating writing 100% test coverage, but just some code that shows how you will be using the new feature as you add it is enough to help you structure your code.
mamcxalmost 7 years ago
I write some test when starting, with the full acceptance most, if not all, will be abandoned. Maybe comment out all the ones I don&#x27;t need anymore or just are too broken (because are invalid). So tests are just another way to do exploratory programming...<p>Most are related to DBs. I NEVER mockup. NEVER.<p>NEVER.<p>I just rebuild the DB each time the tests start (and is PostgreSQL. I found that DROP&#x2F;REBUILD the SCHEMA is <i>fast</i> than drop the database and rebuild, so is ok).<p>This always leave me with all the data in the DB, no matter it fail or not. This is the <i>main reason to never mock</i>. Mock data get lost after the tests end. The db instead persist the data and allow to inspect after the fact.<p>Plus, fill me with the data necessary to let the UI run without re-create again here.<p>This simple rule is what help me most. If I wanna the test to run faster, I can&#x27;t do anything else that write a good database layer and not call the DB when not needed...
评论 #17542175 未加载
danielovichdkalmost 7 years ago
There is a test for that.<p>Try building a tennis game, just in code with no gui, and take note of how much you would either write tests for things like the score, set points etc., or how much time you spend debugging to justify if your code works.<p>Unit tests are a great documentation tool as well, both for developers but also for the business needs of the software — the value.
simula67almost 7 years ago
I have seen statements like &#x27;even bad tests are better than no tests&#x27;. I feel that for unit tests, &#x27;no tests are better than bad tests&#x27;. Failure in unit tests often break CI and I have seen many tests which tests the structure of the code and not it&#x27;s intent. For example, I have seen some tests where the product code is putting some element to a list and the test code checks if the element is present in the list. I can understand why people do it ( they are trying to improve &quot;code coverage&quot; ), however if tomorrow you refactor the code to not put that element in the list, but still accomplish the same thing, the test would break. Often, this breaks CI also and now you are sitting late at office trying to figure out what went wrong so you can push your change into the release. This is valuable time that could be spent on new features, fixing bugs or just going home and relaxing. End to end tests ( or integration tests ) are better since they are real user interactions.<p>If a test fails and it breaks CI, there should be a problem in the product. Move everything else to some &quot;additional testing&quot; bucket and not block developers.
评论 #17542573 未加载
评论 #17540338 未加载
评论 #17540537 未加载
hdialmost 7 years ago
Somewhat interesting but calling an old idea something catchy isn&#x27;t really revolutionary.<p>The article makes a lot of assumptions like &quot;In practice, most agree as most projects set the lower bound for coverage to around 80%&quot;. Most projects where, which industry, who are these 80% that agree? This is just taken out of thin air in this case. It might be true but should we take the author&#x27;s word for it?<p><pre><code> There are also some psychological arguments. For example, if you value unit-testability, you would prefer a program design that is easier to test than a design that is harder to test but is otherwise better, because you know that you’ll spend a lot more time writing tests. </code></pre> This is very subjective without examples. The opposite argument can also be made that code which is easier to test is sometimes better. It felt like reading a collection of quotes and articles by other people.<p>I think TDD, unit, integration and E2E testing works. How much of which to apply is entirely project and industry specific and it&#x27;s up to teams to decide what testing strategy works best for them.
评论 #17540006 未加载
billsmithaustinalmost 7 years ago
&quot;This is because an end-to-end test covers a much greater area of the code base.&quot; I disagree. A single unit test will cover less area than an end-to-end test, but unit tests in aggregate will cover a greater area.
评论 #17542230 未加载
kozakalmost 7 years ago
&quot;Nobody got fired for writing unit tests&quot;, and this makes it hard to justify writing less of them, especially to people that are exposed only to development side of software business.
Jtsummersalmost 7 years ago
&gt; <i>Imagine you have three components, A, B and C. You have written an extensive unit test suite to test them. Later on you decide to refactor the architecture so that functionality of B will be split among A and C. You now have two new components with different interfaces. All the unit tests are suddenly rendered useless. Some test code may be reused but all in all the entire test suite has to be rewritten.</i><p>That&#x27;s not a refactor. That&#x27;s a rewrite or rearchitecturing. Of course you have to redo unit tests, you&#x27;ve eliminated the units that were being tested.<p>&gt; <i>What if you decouple two components that are always used together.</i><p>If they&#x27;re always used together, then they were a unit. Why were they decoupled? See the other front page post about Dijkstra&#x27;s parable for a rather apropos example of where coupling (perhaps not his intended moral) makes sense.
GuB-42almost 7 years ago
It reminds me of a project I worked on. It was for critical embedded software in aircraft (&quot;make an emergency landing&quot; critical, not &quot;we are all dead&quot;). Obviously, the code is certified, with specific requirements (DO-178B level B) and third party audits.<p>And we made the choice not to have unit tests. Everything was done through integration tests. What made up for it is that we had very good traceability. So for we knew which lines of code were related to which requirement and which test. So if we changed some code, we knew which test to run, and if a test fails, we knew where to look at.<p>For the edge cases, we had the ability to inject data directly into memory, triggering the otherwise unreachable error conditions, and the very last cases where done through code analysis (we needed 100% coverage).
guru4consultingalmost 7 years ago
I guess it also depends on the nature of tech stack and business domain. For e.g., if you develop a standard CRUD application without much complexity, and use a static lang like Java, you probably need less unit tests. If you use framework features, annotations, validation expressions, then most of the simple data validations (like numbers, dates, future date check, etc) are automatically handled at framework level. In those scenarios, you would generally need a very little unit test case coverage.<p>On the other side, if you use dynamic lang (Ruby, Javascript, etc), or if you are developing a library or framework, then a good coverage for unit tests is a must. I guess the developer&#x27;s context (whether he&#x2F;she is developing a framework, library or a simple CRUD app) plays a bigger role.
2T1Qka0rEiPralmost 7 years ago
This article makes lots of good claims as to why integration tests can be the most useful area to focus on. I do however think that unit tests can be <i>really useful</i> in encouraging junior developers to improve their plan vs. write approach to software development (if properly guided).
theptipalmost 7 years ago
&gt; unit tests increase maintenance liabilities because they are less resilient against code changes. Coupling between modules and their tests is introduced! Tests are system modules as well.<p>Every time I hear this kind of statement, I think of Bob Martin&#x27;s article: <a href="https:&#x2F;&#x2F;blog.cleancoder.com&#x2F;uncle-bob&#x2F;2017&#x2F;05&#x2F;05&#x2F;TestDefinitions.html" rel="nofollow">https:&#x2F;&#x2F;blog.cleancoder.com&#x2F;uncle-bob&#x2F;2017&#x2F;05&#x2F;05&#x2F;TestDefinit...</a><p>&gt; The author tells of how his unit tests are fragile because he mocks out all the collaborators. (sigh). Every time a collaborator changes, the mocks have to be changed. And this, of course, makes the unit tests fragile... the author of the above blog has given up on badly written micro-tests, in favor of badly written functional tests. Why badly written? Because in both cases the author describes these tests as coupled to things that they should not be coupled to. In the case of his micro-tests, he was using too many mocks, and deeply coupling his tests to the implementation of the production code. That, of course, leads to fragile tests.<p>&gt; What the blog author does not seem to recognize is that first class citizens of the system should not be coupled. Someone who treats their tests like first class citizens will take great pains to ensure that those tests are not strongly coupled to the production code.<p>Testing is hard for a number of reasons, not least because given five engineers you&#x27;ll get six definitions of Unit vs. Integration test. I think the term &quot;micro-test&quot; is useful as a contrast; most beginners sit down and write tests for every significant function, be it public or private (i.e. they write micro-tests), and this produces tests that are tightly coupled to the shape of the code at the time of writing.<p>However if your code is well-encapsulated, and just tested through the public API of your class, then you should be able to make fairly significant changes to the structure of that class without actually changing the tests. (Of course if you change the API then the tests must change; it must always be so).
djhworldalmost 7 years ago
I&#x27;m working on a ticket at the moment that involves a lot of refactoring work to support a new feature.<p>In the initial run on this code base we went a bit unit test crazy, which was fine at the time, but I&#x27;m seeing the drawbacks now where I&#x27;m doing a lot of surgery on the components.<p>I&#x27;ve ended up just beefing up the current integration tests with some extra edge case testing and, after the refactoring work, they still pass, which has given me a lot more confidence.<p>I think a lot of this comes to head when you unit test the glue logic that orchestrates the entire program, unit testing those becomes painful with mocks etc because they become fragile whenever you do any refactoring work.<p>I&#x27;m not sure what to think really.
karmakazealmost 7 years ago
The highezt cost of unit tests is when they are refs tired with code. The value of a unit test is greatest when written before the implemantation. When refactored it is usually just made to pass by any means necessary to stay green without much&#x2F;any thought. They are also brittle in these cases where refactoring the test can take meant times longer than the code it tests.<p>My advice is usually to do tdd for new dev have good coverage of full function tests and delete unit tests if the get in the way&#x2F;lose value on refactoring. No one likes deleting tests but they must add value or its just more debt.
throwaway5752almost 7 years ago
This is ... not even basic test engineering 101. This is remedial: understand the testing pyramid.<p>If you can take a 5ms unit test and verify with 80% confidence for a given feature, run that first before running at 5s system integration test that verifies it with 100% confidence.<p>You run both, because you run unit tests with a build&#x2F;linting stage (something that can run synchronously with every commit, or close to it) and you run the integration test less frequently because of time&#x2F;cost constraints (stable branch merges).<p>Even though they test they same thing, they serve different needs.
edejongalmost 7 years ago
Edsger Dijkstra: &quot;The first moral of the story is that program testing can be used very effectively to show the presence of bugs but never to show their absence.&quot; [1]<p>&quot;I suggest that the programmer should continue to understand what he is doing, that his growing product remains firmly within his intellectual grip.&quot; [1]<p>[1] E.W. Dijkstra: <a href="https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;users&#x2F;EWD&#x2F;transcriptions&#x2F;EWD03xx&#x2F;EWD303.html" rel="nofollow">https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;users&#x2F;EWD&#x2F;transcriptions&#x2F;EWD03xx&#x2F;E...</a>
评论 #17540518 未加载
emodendroketalmost 7 years ago
I&#x27;m not sure if I agree with having a lot of DB tests, but at the same time I definitely have seen the thing where overly specific unit tests make it so painful to change anything that nobody wants to do it.<p>I think &quot;Why Most Unit Testing is Waste&quot; is a better article on this subject. <a href="https:&#x2F;&#x2F;rbcs-us.com&#x2F;documents&#x2F;Why-Most-Unit-Testing-is-Waste.pdf" rel="nofollow">https:&#x2F;&#x2F;rbcs-us.com&#x2F;documents&#x2F;Why-Most-Unit-Testing-is-Waste...</a>
swaggyBoatswainalmost 7 years ago
I started unit testing for the first time several months back. I tried incorporating it into my general workflow<p>Here&#x27;s an isolated overkill example of how unit tests should not be done on one of my codepen files (its a javascript calculator). All tests passed but the calculator is partially broken still. I made about 20 unit test case scenarios when in reality it should have been significantly less (~ about 5 given the complexity of the problem)<p><a href="https:&#x2F;&#x2F;codepen.io&#x2F;vincentntang&#x2F;pen&#x2F;XqNGqv?editors=1100" rel="nofollow">https:&#x2F;&#x2F;codepen.io&#x2F;vincentntang&#x2F;pen&#x2F;XqNGqv?editors=1100</a><p>I ended up getting very little useful feedback on codereview &#x2F; stackexchange, but this is how I felt about unit-testing in general.<p><a href="https:&#x2F;&#x2F;codereview.stackexchange.com&#x2F;questions&#x2F;193128&#x2F;shuntyard-javascript-calculator-with-unit-tests" rel="nofollow">https:&#x2F;&#x2F;codereview.stackexchange.com&#x2F;questions&#x2F;193128&#x2F;shunty...</a><p>I think unit testing is great in some applications (e.g. working with teams as more things can be missed, where a bug can be exponentially cause issues, systems with larger complexity). Doing it in isolated solo projects is such a waste of time IMO, good commenting &#x2F; structurally organizing code&#x2F; naming conventions suffices here. Most things don&#x27;t work in a functional way anyways that makes unit-testing easier. E.g hardware calculators don&#x27;t have logic the way I wrote it in my code above.<p>Unit testing is OPPURTUNITY COST. For a business to implement this the risks of exponential failure and its demand for risk-mitigation should far outweigh the time and developmental practice of implementing it in your training &#x2F; management &#x2F; workflow &#x2F; toolchain.<p>...disclaimer: I might have no idea what I&#x27;m talking about I&#x27;m a fairly inexperienced dev
评论 #17542293 未加载
h0l0cubealmost 7 years ago
I&#x27;m a huge fan of the following essay. It provides a set of very rational, well considered and compelling arguments for less unit tests:<p><a href="https:&#x2F;&#x2F;rbcs-us.com&#x2F;documents&#x2F;Why-Most-Unit-Testing-is-Waste.pdf" rel="nofollow">https:&#x2F;&#x2F;rbcs-us.com&#x2F;documents&#x2F;Why-Most-Unit-Testing-is-Waste...</a>
rbongersalmost 7 years ago
Your testing strategy should be situational.<p>Unit tests can efficiently handle, for example, libraries, error handling which cannot normally be reached, complex algorithms which are not AI based and require a large number of test cases, fragile pieces code and code patterns, and program design patterns which can be tested using inexpensive common tests. Consider the business value of quick tests in each of these situations. It is high.<p>While your units have to come together in a way that allows your users to actually use your software, your business logic has to be represented in whole or in part by one or more unit. Testing this logic earlier on in the process and faster than other types of tests is better.
shinylanealmost 7 years ago
For me this depends on what I&#x27;m working on, and these days my unit tests are generally for API regression. When I&#x27;m writing my APIs, generally my &quot;integration&quot; test would simply involve an external request and assertions of the response. This is fantastic for testing what a client expects, not as good at specific units of business logic where regression can be rather expensive. I would agree many folks take unit testing too far, but in some cases it&#x27;s saved my neck at a pretty small cost of creation.<p>This is probably not the same story for something like a react or swift application. Good read, thanks for the solid points.
migaalmost 7 years ago
I have also been advocating economic approach to testing, but I find this article to be misleading at best.<p>Long-time experience of debugging proves that untested code is worthless. And indeed most people start programming by testing some test case or use case.<p>I would rather recommend starting with use case testing. Data driven testing.<p>Never believe that you can get a code without testing. I guess I finally need to write the article about my <i>diamond testing</i> routine, so that people have something better than unit test swarms ;-)
usrusralmost 7 years ago
Another rule of thumb I like to apply when mix-and-matching different levels of tests: how visible would a bug be in higher level tests? If things will fail in obvious ways, a unit test will give no benefit besides narrowing down the bug location in case of a failure.<p>But if symptoms would likely be too subtle to stand out, e.g. a typical bug would manifest itself in results that seem plausible despite being wrong, then it&#x27;s a strong indication for unit tests.
IanCalalmost 7 years ago
&gt; Integration tests lie somewhere between unit tests and end-to-end tests so they provide the best balance. Therefore, they have the highest ROI.<p>Being in between does not mean it gives the highest ROI or the best balance. They can easily share the worst of both.<p>&gt; Lean Testing takes an economic point of view to reconsider the Return on Investment of unit tests.<p>But does not in any way actually try and work this out, which means that you can&#x27;t make the conclusions that are in this.<p>&gt; The Return on investment (ROI) of an end-to-end test is higher than that of a unit test. This is because an end-to-end test covers a much greater area of the code base. Even taking into account higher costs, it provides disproportionally more confidence.<p>And yet no figures or evidence.<p>Many e2e tests can cover the <i>same</i> path segments, meaning adding a new test may not increase your confidence by much at all. But they&#x27;re still taking longer to run, and despite the articles insistence that integration and unit tests are brittle, I&#x27;ve found E2E tests are also brittle, just in different ways.<p>I shouldn&#x27;t have to change my string normalisation tests just because the website changed moving the resulting output field to a new place on the page. They shouldn&#x27;t break because the login flow changes.<p>I have definitely seen (and written) E2E tests that provide almost no real value, and unit tests that provide huge amounts.<p>&gt; Plus, end-to-end tests test the critical paths that your users actually take. Whereas unit tests may test corner cases that are never or very seldomly encountered in practice<p>Unfortunately low <i>proportions</i> of errors still can account for extremely large <i>actual numbers of</i> problems. 1&#x2F;1000 bugs will happen <i>all the time</i> if you&#x27;ve got a reasonable number of users. Those bugs also may happen to most of your users if they&#x27;re somewhat random, or worse may heavily impact one group.<p>&gt; For many products, it is acceptable to have the common cases work but not the exotic ones (‘Unit Test Fetish’). If you miss a corner case bug due to low code coverage that affects 0.1% of your users you might survive. If your time to market increases due to high code coverage demands you might not survive.<p>Or if roughly one in 1000 customers keep taking your production server down due to a bug you might not, and you may have been just fine waiting another week to go live.<p>I agree with the idea, you should consider what it is you&#x27;re trying to achieve and what the best ways of doing that are. What you absolutely shouldn&#x27;t do is use terms like ROI and economic without any analysis, purely to justify not doing something you don&#x27;t really want to do.
pletnesalmost 7 years ago
The article argues that you should test larger units (integration tests) rather than unit tests, but also that you should use a statically typed language. This leads to less flexibility and more «ossification» in my experience, much like the overly detailed unit tests. Seems to be a contradiction, in my opinion.
thecleaneralmost 7 years ago
Perhaps this approach of end to end testing is great for startups. Although e2e tests can be hard to write, they can be a significant boost when moving with high velocity.
peterwwillisalmost 7 years ago
There are two kinds of end-to-end tests: 1) the software works, 2) the software works in production. The difficulty usually lies in implementing the latter.
actionowlalmost 7 years ago
Unit tests are better than no tests.
mdipalmost 7 years ago
Great article and I&#x27;m somewhat surprised at how often I have to repeat the things mentioned in it -- heck, sometimes it&#x27;s difficult to even convince developers of the value of unit testing, in general.<p>I&#x27;m a huge advocate of automated testing and with the available tools, like docker, it&#x27;s relatively painless to get the pieces together to sort out automated testing. Often the tooling you use to enable automated testing is tooling you end up needing <i>anyway</i> -- it&#x27;s dual purpose. Before the &quot;first run&quot; of a set of code, I&#x27;ll create Dockerfiles that make up a complete, local, development instance of an application along with some boilerplate tooling that I include to make debugging easier on me. When setting up the production build, the final version is usually <i>this same environment</i> with fewer lines in the file. Because my environments tend to be similar, I have a zsh script that strips out lines in the Dockerfile to get me 90% of the way to a production container.<p>For me, it&#x27;s <i>always</i> worth it. I came to this conclusion after spending a few months <i>forcing</i> myself to test rigorously[0], starting with unit tests written often and early and ending with a small number of integration tests and a much smaller number of end-to-end tests. I don&#x27;t find any of these particularly difficult to write.<p>The benefits, however, are vast: (1) Avoiding the debugger time-sink: The #1 thing that I always come back to is that I generally end up <i>never</i> having to fire up a debugger. I noticed that every time I encountered a bug in code that was poorly covered, the first instinct was to attach a debugger and peek at locals to see what was going on. This rarely resulted in spending less than an hour troubleshooting. Sometimes you get lucky and you find more than one issue in that debugging session, but often it landed in at burning an hour on ever bug and way too often it was an hour spent debugging <i>production code</i> and the bug was <i>customer impacting</i>[1]. At the same time, it&#x27;s rare for an automated test to have a time cost that high. (2) Refactoring - Since &quot;premature optimization is the root of all evil&quot;, that necessarily means that a performance bug is going to involve injecting complexity into a running codebase and this often comes with high-impact refactoring. Unit tests, specifically, are incredibly helpful here. This is often an argument <i>against</i> integration&#x2F;end-to-end test automation since refactoring regularly breaks these brittle tests, however, I&#x27;ve found in practice that this isn&#x27;t the case at least half the time. Of the times that it <i>does</i> affect those tests, the practice of refactoring can surface subtle bugs (on a few occasions it surfaced a subtle race condition that might have been missed if a few of the integration tests covering a subset of the functionality hadn&#x27;t broken). (3) Design - more for integration and unit tests, thinking about testing while writing code can result in a less brittle design[2]. On integration tests, it means writing SQL scripts and migrations to ensure that a fresh environment can be spun up on-demand instead of using GUI tooling (or, using the GUI tooling to generate said scripts&#x2F;migrations). (4) Build automation - I&#x27;m somewhat surprised at how often I encounter a customer project where I have to follow a 20 step process to get things functional in a development environment. It seems like if CI isn&#x27;t involved, people figure a README.md with a mess of shell commands and button clicking is OK. Scripting out environment configuration and build was already one of the first things I did when I began running the code I&#x27;d written, however, I find I no longer have to argue in favor of this when testing is involved -- everyone wants a single command to execute tests and once integration and end-to-end tests are involved, it just makes sense to add standing up the docker parts, too[3].<p>I get why there&#x27;s resistance to doing these things -- getting people to simply write <i>any</i> automated tests seems to be the most difficult hurdle. Throw in &quot;learn docker&quot; and other technologies to make automated end-to-end testing easier and the barrier is even higher. And hey, there are some times that the time spent writing tests doesn&#x27;t pan out to a time savings. For the unconvinced, I can only <i>strongly</i> recommend: try it on your next big project. There&#x27;s no need to change the way you think -- skip TDD if it doesn&#x27;t work for you -- but write unit tests over your, public facing surface area. Write integration tests over the most important parts of your codebase -- those which if a bug were to be encountered would have the greatest impact on reliability. Write a few end-to-end tests of major functionality. Keep track of the time spent from the first line of code to the final, released, product. If your experience is like mine and the 4 different teams I&#x27;ve done this exercise with, you&#x27;ll end up doing things this way from that point forward. If not, you have a gift that I lack -- you write incredibly bug-free code &quot;the first time&quot;, every time. :) Then try switching to a single 1080P monitor[4].<p>[0] I tend to code first, test second. Though, on paper, TDD looks like a good idea in that it forces you to think about the desired outcome and write methods in a manner that guarantees the ability to test, I don&#x27;t find it difficult to write things in this manner from the beginning and I find it more natural to write the actual code first and I&#x27;ll often write a large footprint of code before writing the first test -- I don&#x27;t find as much value as others in frequent, instant, feedback but I recognize the value that others find in that.<p>[1] And bugs resolved during an outage are duct-tape &quot;there, I fixed it&quot; kind of repairs.<p>[2] Provided you don&#x27;t like having to figure out new and creative ways to mock complex god-objects&#x2F;routines. Maybe you dig that sort of thing?<p>[3] I reload enough that I have a script that automates <i>installing and configuring</i> docker in the most common manner if it&#x27;s missing or the configuration isn&#x27;t complete.<p>[4] <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14482587" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14482587</a>
jfjfjfjfyyalmost 7 years ago
The dogma around unit testing, TDD and the book selling test hype cycles have caused immeasurable damage to software development as technical and scientific disciplines.
评论 #17540243 未加载
kazinatoralmost 7 years ago
I think I can articulate what I find distasteful about approaches like TDD: it&#x27;s basically a &quot;how to program&quot; recipe for people who have absolutely no talent. Like &quot;paint by numbers&quot;. It&#x27;s tone-deaf toward the creative aspects of development: the Art, if you will.<p>TDD for music composition: add some notes which jar the ear (red test). Then massage them until they sound pleasing (green test). Make some adjustments for better flow with surrounding notes (refactor). Now repeat. Gee whiz, you&#x27;re gonna be the next Mozart or Bach!
评论 #17542781 未加载
irundebianalmost 7 years ago
Time-to-market is the only valid argument for writing crap code and not unit tests. I&#x27;m not sure if you can seriously argue with economic reasons when talking about testing. The most costs in software development arise in the operations&#x2F;maintenance phase and are probably (there are much papers on this topic) multiple times higher than the costs of the implementation phase.<p>I agree that every software development team has to make their own decision to balance development time and maintenance cost but I don&#x27;t agree with this low entitlement mentality of writing correct code in this article.<p>Of course there are also costs when implementing tests and your unit tests are rendered useless on design changes. But so what? You&#x27;re also decreasing code assurance and it&#x27;s better to increase it with tests so that you won&#x27;t encounter bugs in production which is much more expensive than writing tests.<p>Software development is not only about adding functionality but also about ensuring its correctness.
评论 #17542057 未加载