tags:

views:

1031

answers:

20

I have read a lot of threads about the joys and awesome points of unit testing. My question is, does anyone have a good argument against unit testing?

+20  A: 

It's important to understand that it's not free. Tests require effort to write - and, more importantly, maintain.

Project managers and development teams need to be aware of this.

duffymo
I disagree. Coding with Unit Tests goes faster than coding without Unit Tests. The net-effect is faster development even though you have to write code for unit tests. If your net effect is slower, you might want to try harder to do TDD (test first).
leonm
@duffymo: well, this is sort of true, but the test zealots will counter by saying that the cost is more than made up downstream in improved confidence and reliability when making changes.
Chris Farmer
Initially, though, before your team has ever done unit-testing it will take longer to write your code. Once you get over the initial hurdle of just writing some tests first, you will come to see the benefit in productivity and hence, the benefit in time.
Jake
I agree with those teams, but it would be good to see some real data. Nobody seems to have much of it. The arguments smack of religion. "Zealots" is the right word.
duffymo
@leonm - I didn't make any statement about whether it was faster or better. All I said was that it wasn't free. Effort was needed to create them and maintain them. If they aren't kept up, they lose their value. The second law of thermodynamics holds.
duffymo
Here is some data, even though it's on TDD and not unit testing per se: http://research.microsoft.com/en-us/projects/esm/fp17288-bhat.pdfBottom line is, it takes 15% more time, for a big quality improvement.
Mathias
I'm not sure this is right. If you have 86% code coverage, so the number of classes and methods for test and production code are almost equal, how can it be that it only takes 15% of the time to write that test code? It's a nice paper, though.
duffymo
@leonm: not everything can be tested by unit testing.
SigTerm
Even then, unit testing can only test known cases. If you forget to exercise a function in a particular way or incorrectly write your test or use case the related units tests are useless and will not find a bug. If you worry about 100% code coverage you will spend tons of time working on test code instead of the production code that makes money. Unit testing is a cool and useful idea... as long as it's done with someone else’s money.
Matthew Whited
I think a lot depends on the size of the project and team.
Brian MacKay
It also takes time to learn how to write unit tests well, in a sustainable fashion.
Ben
This argument demonstrates a lack of deeper understanding of what software development really is, and what takes up the time of a team. I could probably talk for half an hour on this, but in short. If you don't test, cost of defect detection and fixing grows at a rate multiplied times the cost of unit tests. If you don't have fast unit tests, the velocity of the team going forward implementing new functionality is significantly reduced compared to when you have them. So when talking about cost, you must include total cost of ownership, and not optimize locally for a handfull of programmers.
Mahol25
We all get it, Mahol. You aren't the sole owner of a deeper understanding. All I said was that the cost wasn't zero, and to imply otherwise is misleading. I'm also saying that you have a problem in quantifying your deep understanding. You can't calculate total cost of ownership with and without testing. We all understand the value, but we can't put a dollar figure on it.
duffymo
+3  A: 

Laziness, sometimes i'm lazy and just don't wanna do it!

but seriously unit testing is great, but if im just coding for my own enjoyment i generally don't do it because the projects are short lived, im the only one working on it, and they're not that big.

luke
+3  A: 
  • It can discourage experimenting with several variations, especially in early stages of a project. (But it can also encourage experimenting in later stages!)

  • It can't replace system testing, because it doesn't cover the relationship between components. So if you have to split up the available testing time between system testing and unit testing, then too much unit testing can have a negative impact on the amount of system tests.

I want to add, that I usually encourage unit testing!

Chris Lercher
+2  A: 

I wouldn't say it's an argument against it, but for us we have a legacy application with a TON of code, and written in COBOL. It is virtually impossible at this point to say we want to implement unit testing and do it with any degree of accuracy or within a reasonable time frame for business as pointed out by duffymo.

So I guess to add onto that, maybe one argument would be the inability(in some cases) of trying to implement unit tests after development has been completed(and maintained for years).

jaywon
+9  A: 

You have a data access layer that isn't easy adapted for mocking.

Joshua
+4  A: 

It's the usual cost/benefit analysis.

Cost: You need to spend time developing and maintaining the tests, and put resources into actually running them.

Benefits are well known (mostly cheaper maintenance/refactoring with less bugs).

So, you balance one against the other in the context of the project.

If it's a throwaway quick hack you know will never be re-used, unit tests might not make sense. Although to be honest, if I had a dollar for every throwaway quick hack that I saw running years later or worse, had to maintaing/refactor years later, I'd probably be able to be one of venture capitalists investing into SO :)

DVK
Every time anyone says something hyperbolic about throwaway quick hacks, a fairy dies.
walkytalky
@walkytalky: I **hate** fairies.
Xiong Chiamiov
... only try to realize the truth. There are no faeries. Then you'll see, that it is not the faeries that suffer, it is only yourself.
DVK
+18  A: 

Virtually none of my bugs would have been found by unit testing. My bugs are mostly integration or unexpected-use-case bugs, which in order to have found them earlier, more extensive (and ideally automated) system tests would have been the best bet.

I'm waiting for more evidence-based and less religion-based arguments for unit testing, as dummymo said. And I don't mean some experiment in some academic setting; I mean an argument that for my development scenario and programming ability, cost-benefit would be positive.

So, to agree with other answers to the OP: because they cost time and cost-benefit is not shown.

Conrad Albrecht
In my real-life experience, unit tests are useful for 1) explicitly stating what use cases should be successful - good for documentation and showing _what_ a feature does (not how) 2) Catching bugs - mostly design bugs, because you start at the interface and work downward and 3) Regression testing. You can hack away with impunity knowing that your test suite will alert you if you've broken anything. These 3 things, again in my experience, more than justify the cost.
Matt
I don't deny that unit tests can provide all of those benefits. But I think system tests provide the same benefits almost exactly, plus catch lots of bugs which unit tests will miss. Plus system tests require less rewriting when refactoring, because if the external behavior doesn't change then the system tests are still valid, but the unit tests for the refactored classes have to be replaced.
Conrad Albrecht
I'll bet most of the people voting this up want an excuse to be lazy; however, I think he's right more often than not.
Joshua
+3  A: 
  • Testing is like insurance.
    • You don't put all your money in to it.
    • But you don't avoid your life insurance. (People form US should still be remembering the Health Insurance Bill).
    • Insurance is ESSENTIAL evil.
    • BUT BUT BUT...
      • You don't get insured expecting a Fatal accident to recover all the money you put into your insurance plan.

In summary,

  • There is SOME reason to write Tests.
  • Unit tests are sometimes One of the many ways to go forward
  • BUT There is NO REASON to just to focus entirely on writing (Unit) Tests.
Meera
lol @ the fear of healthbill
Darren Kopp
Unit tests are like anti-virus software: not necessarily bad, but often misused as a substitute for sensible behaviour and critical thinking.
walkytalky
@walkytalky: I'd hardly call OS management critical thinking.
Matt Joiner
+3  A: 

The simple truth is, when you write some code, you have to make sure it works before you say it's done. Which means you exercise it - build some scaffolding to call the function, passing some arguments, checking to make sure it returns what you expect. Is it so much extra work, to keep the scaffolding around, so you can run the tests again?

Well yes, actually, it can be. More often than not the tests will fail, even when the code is right, because the data you were using is no longer consistent, etc.

But if you have a unit testing framework in place, the cost of keeping the test code around can be only marginally more work than throwing it away. And while yes, you'll find that many of your test cases will fail because of problems with the data you are using, instead of problems with the code, that will happen less as you learn how to structure your tests so as to minimize the problem.

True, passing your unit tests does not guarantee that your system works. But it does provide some assurance that certain subsystems are working, which isn't nothing. And the test cases provide useful examples of how the functions were meant to be called.

It's not a panacea, but it's a useful practice.

Jeff Dege
+4  A: 

Unit tests will tell you whether one specific class method sets a variable correctly (or some variation on that). That does not, in any way, shape, or form, indicate that your application will behave properly or that it will handle the circumstances it will need to handle.

Any problem you can think to write a test for, you are going to handle in your code, and that problem is never going to show up. So then you have 300 tests passing but real-world scenarios you just didn't think to test for. The effort required to create and maintain the tests, then, isn't necessarily worth it.

I mostly agree. But just because you knew something at the time you wrote the test -- and coded accordingly -- it doesn't mean you'll *still* know it in year's time when you rewrite the code for what seem like excellent reasons.
walkytalky
As walkytalky is alluding to, if someone else has to implement new requirements with code you wrote 10 years from now, and you're not available, unit tests are how you can still (even if you are dead) test the software as they work on it.
apollodude217
A: 

Instead of completely getting rid of them, we write unit tests only for core functionality such as payment authorization, user authentication, etc etc. It is very useful as there will always be some touch points that are very sensitive to code changes in a large code base and you would want some way to verify those touch points work without failing in QA.

CodeToGlory
+25  A: 

In the places i have previously worked, unit testing is usually used as a reason to run with a smaller testing department, the logic is "we have UNIT TESTS!! Our code can't possibly fail!! Because we have unit tests, we don't need real testers!!".

Of course that logic is flawed. I have seen many cases where you cannot trust the tests. I have also seen many cases where the tests become out of date due to tight time schedules - when you have a week to do a big job, most devs would spend the week doing the real code and shipping the product, rather than refactoring the unit tests for that first week, then pleading for at least another week to do the real code, and then spending a final week bringing the unit tests up to date with what they actually wrote.

I have also seen cases where the business logic involved in the unit test was more monstrous and hard to understand than the logic buried in the app. When these tests fail, you have to spend twice as long trying to work out the problem - is the test flawed, or the real code?

Now the zealots are not going to like this bit: the place where i work has largely escaped using unit tests because the developers are of a high enough calibre that it is hard to justify the time and resource to write unit tests (not to mention we use REAL testers). For real. Writing unit tests would have only given us minimal value, the return on investment is just not there. Sure it would give people a nice warm fuzzy feeling - "i can sleep at night because my code is PROTECTED by unit tests and consequently the universe is at a nice equilibrium", but the reality is we are in the business of writing software, not giving managers warm fuzzy feelings.

Sure, i admit there are uses for unit tests. The trouble with unit testing and TDD is:

  • too many people bet the family farm on it
  • too many people use it as a religion rather than just a tool or another methodology
  • too many people have tried to make money out of it, which has skewed how it should be used

In reality, it should be used as one of the tools or methodologies that you use on a day to day basis, it should never become the single methodology.

slugster
REAL testers are great, however many companies dont have them. they have some random people of the street to test the app.
01
Conversely I've seen all these same reasons used as an excuse for laziness. "We have real testers, why should I bother to write tests for my code?" Automated unit tests aren't a replacement for QA but they relieve QA testers from tedious regression testing so they can focus on finding new bugs. Unit testing is like double-entry accounting. It may take a little longer to write but it catches errors as they happen rather than days, weeks or years after they've occurred.
codeelegance
@code, i agree. I did enjoy the chance to have a good moan about unit testing because i've seen it used badly too often or the wrong emphasis placed on it. However i don't think it should replace or diminish regression testing, but that is a whole other argument.
slugster
I do not see objective arguments. Just complaining that people do not utilize unit testing properly.
Yauheni Sivukha
@Yauheni, i expect a few people to disagree. My answer is full of objective reasons (based on real life experiences), most centred around the fact that organisations use unit tests badly and expect the wrong things from them, and that unit tests should never replace proper testers.
slugster
@slugster, The only reason you gave - There are few developers who can write good tests. I agree with this statement, but I do not agree that this is the reason to reject unit testing - this is the reason to teach developers.As for testers replacement. Automated testing (including unit testing) was never intended to replace real testers.
Yauheni Sivukha
@codeelegance: In "Automated unit tests...tedious regression testing", I think you're presenting a false choice. Regression/system tests can also be automated -- appears to me you conflate "unit" with "automated".
Conrad Albrecht
@slugster - Not to throw oil on the fire (and not offering an opinion of the content itself) but Yauheni is right, your responses are subjective...not objective.
Webjedi
@slugster - The first few arguments are against bad unit tests, not TDD. The argument that your team has seen more cost than benefit, however, is an argument against unit testing.
apollodude217
I don't think it matters if you cannot objectively prove what he's saying is true for most places because you can't disprove it either. In my experience TDD has produced unhealthy ways of thinking without much gain for every single company I've worked at and I sincerely doubt there are a lot of exceptions floating out there - hence why his answer was voted up so many times.
hyprsleepy
A: 

There is never a reason to never write unit tests.

There are good reasons to not write specific unit tests. (Especially if you use code generation. Of course you could code generate the unit tests to make sure nobody has mucked with the generated code. But that is dependent upon trusting the team.)

*Edit

Oh. And from what I understand some things in functional programming either compile thus work or don't compile.

Would those things need unit tests?

ElGringoGrande
Do you write unit tests for your nuclear power plant? In a simulator maybe...
Longpoke
@Longpoke: Those are called integration tests.
Joshua
A: 

In Test Driven Development, the unit tests are actually more importantly a way to design your code to be testable to begin with. As it turns out your code tends to be more modular and writing the tests helps to flesh out APIs and so forth.

Too often though, you find yourself developing the code then writing the tests, commenting out the code you just wrote to ensure that the tests fail, then selectively removing the comment tokens to make the tests pass. Why? Well because it's much harder to write tests than it is to write code in some cases. It's also often much more difficult to write code that can be tested in a completely automated way. Think about user interfaces, code that generates images or pdfs, database transactions.

So unit tests do help a lot, but expect to write about 3 times as much code for the tests than you will write for the actual code. Plus all of this will need to be maintained. Significant changes to the application will invalidate huge chunks of tests - a good measure of the impact to the system but still... Are you prepared for that? Are you on a small team where you are doing the job of 5 developers? If so then automated TDD development just won't fly - you won't have time to get stuff done fast enough. So then you end up relying on you're own manual testing, QA testing stuff as well and just living with bugs slipping through and then fixing things up ASAP. It's unfortunate, high pressure and exasperating but it's reality in small companies that don't hire enough developers for the work that needs to be done.

Khorkrak
"3 times as much code for the tests than you will write for the actual code" - What is this estimate based on? My experience has been much less test code per production code.
apollodude217
Every line of production code must be tested. 100% code coverage. There are multiple paths through the code typically. Therefore you will end up with a heck of a lot more test code than production code - that is unless you're not thinking through of all the test cases required to thoroughly define what the preconditions and post conditions are for each method.How did I come up with this number? Simple - counted the lines of code on multiple projects done over the years - various developers involved. Averages about to 3x.
Khorkrak
+4  A: 

Formal verification.

If you can formally prove the correctness of code, there is no reason to unit test it unless the test condition brings in new variables, in which case, you'd still only have a small amount of unit tests (or prove for the new variables).

Longpoke
why -1?????????
Longpoke
@Ben: "wide open to interpretation"? I don't get it. If you can formally prove the correctness of code, there is no reason to unit test it unless the test condition brings in new variables, in which case, you'd still only have a small amount of unit tests.
Longpoke
@Ben, hmm good idea. Done.
Longpoke
Except for trivial cases, even if you can (are able to) formally prove something, _you'll probably screw it up_, which is why we test everything: http://thedailywtf.com/Comments/The-Proven-Fix.aspx. Just like I _can_ shoot a basketball into a goal, but that doesn't mean I _will_ just by trying--I mess it up randomly.
apollodude217
+1  A: 

It is impossible to generalize where unit tests are going to provide cost-benefit and where they are not. I see a lot of people arguing strongly in favor of unit testing and blaming people who don't for not using TDD enough, while completely ignoring the fact that applications can differ as much as the real world does.

For instance, it is incredibly hard to get anything useful out of unit tests when you have a lot of integration points, either between systems, and/or between processes and threads of your own application.

If all you ever did were websites like Stackoverflow, where problem domain is well understood, and most solutions are fairly trivial, then yes, writing unit tests have a lot of benefits, but there are lots of applications out there that simply can't be unit tested properly, as they lack, well, "units".

HeavyWave
+2  A: 

Non-deterministic outcomes.

In simple cases you can seed the random generator(s) (or mock them somehow) to get reproducible results but when the algorithm is complex this becomes impossible as code changes will alter the demand for random numbers and thus alter the results.

This would rarely be encountered in a business situation but it's quite possible in games.

Loren Pechtel
Non-deterministic outcomes are one area where you should especially use unit tests as you can (both!):-mock away the random generator to test all (combinations of) corner cases and one normal case.-run the test with the non-determinism a bazillion times. In this case, you probably want to record the random inputs so you can repeat a problem. But even if you can't do that, unit testing is still worthwhile.
apollodude217
You can't mock away the effect of the random generator if the situation is complex. What happens when you make a change to the code that changes the calls to the random generator? I just hit one of that sort--fixing the bug ended up changing how it selected a random item to remove and thus changing the behavior of the generator from that point on.
Loren Pechtel
+2  A: 

I agree with the notion that there are no good arguments against unit testing in general. There are some specific situations, however, where unit testing may not be a viable option or is at least problematic and/or poses a difficult return-on-investment proposition for the level of effort involved to create and maintain tests.

Here are some examples:

  • Real-time-dependent behavior in response to external conditions. Some purists may argue that this is not unit testing but rather involves scenarios at an integration or system testing level. However, I've written code for simple, low-level functionality for quasi-embedded applications where it would be useful to at least partially test real-time response via a unit-testing framework for build/regression testing purposes.

  • Testing behaviorial and/or policy-level functionality that requires a complex data description of the environmental state to which the tested code module is responding. This is related to an earlier poster's comment regarding the difficulty of doing unit testing involving a data access layer that isn't easily adapted for mocking. Although the behavior/policy being tested may be relatively simple, it needs to be tested across a complex state description. The value of doing unit testing here is in assuring that rare yet key conditions are handled correctly for a mission-critical application. One wants to mock the latter and create a simulated environment/state, but the cost of doing so may be high.

There are at least two alternatives to unit testing for the above scenarios:

  • For real-time or quasi-real-time functionality testing, extensive system testing can be done to try to compensate for the lack of good unit testing. For some applications this may be the only option, e.g., embedded systems involving hardware and/or physical systems.

  • Create a test harness or system-level simulator that facilitates extensive testing across a range of randomly simulated conditions. This can be useful for testing the policy/behavior scenarios described earlier involving a complex environmental state. Although significant work may be involved in creating the test harness or simulator, the return-on-investment may be a much better value than for isolated unit tests since a much broader range of conditions can be tested.

    Since the test environment involves random rather than specific conditions, this approach may not offer quite the level of assurance desired for some mission-critical scenarios. Conducting extensive tests may help make up for this. Alternatively, creating a test harness or system simulator for random conditions may also help with reducing the overall cost of testing specific complex state scenarios since the development cost is now shared across a broader range of testing needs.

In the end, how to best approach testing any given application comes down to cost vs. value. Unit testing is one of the best options and should always be used where feasible, but it is not universally applicable to all scenarios. Like many things in software, sometimes it will just be a judgment call one has to make and then be prepared to make adjustments based on the outcome.

Joel Hoff
"there are no good arguments against unit testing in general." I almost agree, except I consider testimonies ("It didn't work for me") significant.
apollodude217
A: 

No, really I don't. In my experience people who do are presenting a straw man's argument or just don't know how to unit test things that are not obvious how to unit test.

@Khorkak - If you change a feature in your production code, only a handfull of your unit tests should be affected. If you don't that means that you are not decoupling your production code and testing in isolation, but instead excecising large chunks of your production code in integration. That's just poor unit testing skills, and yes it's a BIG problem. Not only because your unit test code base will become hard to maintain, but also because your production code base will suck and have the same problem.

Mahol25
+1  A: 

For writing unit tests in general, learning curve is the biggest reason I know of to not bother. I have been trying to learn good unit testing for about 1.5 years now, and I feel like I'm just getting good at it (writing audit log spies, mocking, testing 1 constraint per test, etc.), although I feel it has sped up development for me for about 1 year of that time. So call it 6 months of struggling through it before it really started paying off. (I was still doing "real" work during that time, of course.)

Most of the pain experienced during that time was due to failure to follow the guidelines of good unit testing.

For a variety of specific cases, ability to unit test may be blocked; others have commented on some of those.

apollodude217