Skip to content

Your Unit Tests Lie to You

February 17, 2009 by Janusz Marcin Gorycki

Photo (c) Janusz Gorycki

Achtung: A Bunch of Obvious Statements Below

Continuing the grand tradition of writing "controversial" posts, let's take a look at unit tests - which for some folks seem to be the new gospel, the best thing since sliced bread, the cure to all our ailing.

Well - the truth is that, in the agile community unit tests seem to be a little bit overrated. Or, to be more precise - they are often incorrectly used as a "silver bullet" substitute for the tedious, labor-intensive, time-consuming, boring and un-gratifying, manual integration and system tests. They quite often, and wrongly, become the one and only QA process in the project. Let me tell you - these hope of getting rid of integration and system testing are false and maintaining them is extremely dangerous.

The Purpose of Unit Testing

Unit tests are a good tool for two purposes:

  • they are a fast and simple verification vehicle, allowing you to test your unit's responses to variety of external stimuli - either ones that you could think of while developing, or ones simulating conditions that led to a bug in your code (if these conditions can be reduced to a unit test, which may or may not be the case)
  • they give you a cerating assurance that the code you have created for the unit will not be so easily broken in the future by somebody who is refactoring it for whatever reason (bug fixes, improvements, rearchitecting, whatever)

And that is pretty much it.

All other valid reasons for unit testing can eventually be reduced to these two. I remain in a violent disagreement with some of the other "qualities of unit testing" listed in the linked blog post of my esteemed colleague. I won't attempt to go over them one by one here though, for the lack of space.

Don't get me wrong - unit tests are extremely useful - these days they are quite essential. Applying unit test to your code will make it better. You should absolutely be unit testing your code, whenever possible. You should be trying whenever possible to create unit tests mimicking conditions that led to reported bugs. But - it is a criminal offense to stop there. And it is an even bigger crime to insinuate that unit testing alone is a sufficient QA process for any sort of serious software project.

Ok, So How do They "Lie"?

Let's try to answer the question of what purposes unit test are not useful for, or what are the dangers of relying on them, shall we?

  • Unit test are not a necessarily a means for documenting your system, sorry. I have seen a fair amount of unit test that did, and an even larger pile of those that didn't, instead increasing chaos and miscommunication. Tests will only become your system's docs, if you create them with this specific purpose in mind. The same can be said about your actual code - it may or may not be self-documenting
  • "Green" (all passing) unit tests don't necessarily mean that your system is healthy. It is not humanly possible to test for every scenario, you can break your system in many funky ways and still make your even most stringent unit tests pass. Boy, do I have stories to tell about that one...
  • Trusting your unit test mocks is wrong. Mocks are only able to superficially mimick the real world. Claiming that mocks can substitute the real environment is like claiming that a blowup doll is a good approximation of a marriage
  • They are worthless if they are slow. In a non-trivially large system, unit testing can take hours (if not more) - and your automated build will take the same amount of time. This makes unit tests worthless as a vehicle for instant feedback - nobody will bother waiting half a day for the results of a build after they committed some refactored code. Yes, you can and should partition your code to smaller modules, but then your builds do not test everything - they only test your module

All of the above are valid problems (and I challenge you to prove me wrong), but the next one is the kicker:

Even if you are a master programmer, you have no idea what to test for. There, I said it. And I have a war story to back me up:

One of the best developers in our team has created a fine piece of code, unit tested the hell out of it and was proud as a baby of his accomplishment. And a fine piece it was indeed - chapeau bas! Yet - it failed "in the field". Its problem was performance - it failed to be efficient in the face of real-life conditions. And the developer in question could't quite believe his eyes whan somebody else on the team investigated the problemand pointed out where exactly in his code the root cause of the problem was - it was a classical case of "this one is obviosly correct, it is not necessary to test it". So if this bloke is unable to create proper unit test suite (and his software development skillz are absolutely top-notch), nobody can.

So please, don't fire your QA department just yet. Their job is still important, even if you unit test.

AttachmentSize
blueface.jpg43.73 KB

About the Author: Janusz is a software developer and team manager with over 15 years of experience. He has been working for a long time for multi-national corporations, mainly in the telecommunication and embedded systems industries, He is now a co-owner of SPARTEZ - an independent agile consulting and software development company

Comments

I strongly agree as well as

February 17, 2009 by pbielicki, 51 weeks 8 hours ago
Comment id: 2236

I strongly agree as well as disagree with what you wrote - especially with >>Ok, So How do They "Lie"?<< part which contradicts my post. The fact is that I wrote pros and you wrote cons of unit tests - it's the same difference when comparing "Hey, I will live about 30 more years!" and "Oh God! I'm gonna die in about 30 years". Well, somebody who is 40, or 50, or even 60 will be right saying both sentences - it's the questions of attitude and what he/she wants to convey. If you want to prove that unit tests are not good for everything you would probably disclose all things that suck. If you want to convince somebody to start writing unit tests you would probably describe all good things you can achieve by doing so.

Nobody said unit tests are good for everything - especially for performance testing where you have to have dedicated performance tests. And nobody said that unit tests can lead to firing QA department - unit tests are developers tests (and I consider them ONLY developer's tests). You sill have to perform zillions of other tests to be sure your system does WHAT and in the WAY it has to do.

To conclude - generally unit tests don't lie to you. And yes - they lie to you if you want to test performance by just unit testing your code.

Test for contract

February 17, 2009 by sginter, 51 weeks 8 hours ago
Comment id: 2237

Believe me or not, I mostly agree with you ;-)

However, as a not-so-master programmer I can only advise you to test for method/class/unit contract.
Write a few tests for expected ('normal') inputs, then identify and test corner cases (that you know of), add some clearlyinvalid inputs to see if the code fails gracefully.
You will add new test cases when you start fixing bugs later - you will know what to test for.

There are quite a few reasons why unit tests are really useful, but as you mentioned - megabytes have already been written on this topic, let's save the bandwidth.

Unit Tests work best for defined units

February 17, 2009 by Ricky Clarkson (not verified), 51 weeks 6 hours ago
Comment id: 2238

Unit tests will only show flaws in the internal consistency of software, not whether it works outside the programmer's understanding of the unit's purpose. This can make unit tests seem useless, but being more confident of the internal consistency allows one to more readily adapt when the purpose of the unit becomes clearer.

The same is true of types, but types show the absence of flaws, not the presence of them.

Missing a trick

February 17, 2009 by Keith Braithwaite (not verified), 51 weeks 6 hours ago
Comment id: 2239

his software development skillz are absolutely top-notch

Clearly, they are not. He's missing a trick.

it was a classical case of "this one is obviosly correct, it is not necessary to test it"

This is why the discipline of test first (or even better, test-driven) is so important. Having someone working with you to reply "yes it does" when you claim "this case doesn't need a test" helps a lot too.

Unit testing isn't sufficient but it is a huge help. It helps most when done in the most effective way. Somehow these hugely effective bits of technique get mentioned less and less. A shame.

What about the other 99.9999% of times

February 17, 2009 by Pramatr (not verified), 51 weeks 4 hours ago
Comment id: 2241

I agree with many of the points here, you can't just get rid of QA, you can't just rely on unit tests for everything but they do have their place. I'm always suspicious of anyone thats going to tell me they have one cure for all ills.

So if this bloke is unable to create proper unit test suite (and his software development skillz are absolutely top-notch), nobody can.

Ok so what about the other 99.9999% of times he wrote unit tests, did they suffer from the same problem as well? Are we just talking about an insolated incident or did he always just *miss* things. Many of the bugs we find are because an area doesn't have test coverage or it's something that simply can't be unit tested. We still need QA on this, they aren't going anywhere.

NOT missing a trick

February 17, 2009 by Janusz Gorycki, 51 weeks 2 hours ago
Comment id: 2242

Believe it or not, but the bloke in question is the most religious of us all in our team when it comes to all things TDD - including "test first". But (and it is a very, very big but) in ANY non-trivial system, it is simply not possible to think of all possible scenarios and test every possible stimulus that may happen to interact with your code.

I can bet you that nobody (including me, you and every other reader of this post) would be able to figure out the potential problem in this code just by doing a TDD on it.

What is in the contract?

February 17, 2009 by Janusz Gorycki, 51 weeks 2 hours ago
Comment id: 2243

Mostly +1 to what you said. But - it is not always clearly defined WHAT the contract of your unit actually is (it doesn't matter if it is formalized or not). Does the contract include performance characteristics? Memory consumption? Behaviour in "disaster" conditions (out of memory, out of disk)? People can and will use your unit in ways that will make your hair grey. You won't be able to predict all perverted ways your module is going to be misused.

Having said that - you should still try :)

How much do you expect by unit test?

February 17, 2009 by alepuzio (not verified), 51 weeks 22 min ago
Comment id: 2244

Hi,
I read your critique to unit testing. I agree with your sentences, but in my opinion you present the limits of the unit testing, not the defect.
1. Unit test are not a necessarily a means for documenting your system: true, but if the choice is No documentation in natural language, UML diagrams, etc and Doc only with unit test then the unit testing is very necessary.
2. "Green" (all passing) unit tests don't necessarily mean that your system is healthyTrusting your unit test mocks is wrong A lot of time it's a problem of response to questions: "What are the conditions where the test is matter?"

bye

As described, the trick WAS missed

February 17, 2009 by Keith Braithwaite (not verified), 51 weeks 15 min ago
Comment id: 2245

I'm confused. You wrote:

the developer in question could't quite believe his eyes whan somebody else on the team investigated the problemand pointed out where exactly in his code the root cause of the problem was - it was a classical case of "this one is obviosly correct, it is not necessary to test it".

So as described he did think of the case and then decided not to test for it.

By the way, it's true that not you, nor I nor anyone else can think of all the cases for a non-trivial system. We can't for most trivial ones, neither. Which is why we still do need integration testing and QA (although as much of that as possible should be automated: humans should write tests, not do testing). But who's saying otherwise? I've been doing TDD for nearly ten years and intensively unit testing code post-hoc for longer than that and I don't know anyone who's claiming that unit testing removes the need for QA. Przemysław in particular makes no such claim in the posting that you reference.

hmm

February 17, 2009 by Janusz Gorycki, 50 weeks 6 days ago
Comment id: 2246

Yes, he _did_ think of this case and decided not to test for it. Just as when he/you/whoever spot a "for" loop and decide _not_ to test whether your compiler generates proper assembler code for it - and believe me, sometimes you should! The problem is - you don't know that you should beforehand, only after your code craps out. But even after that, you really don't start retrofitting unit tests on _all_ your "for" loops, do you?

Someone Crazy

February 17, 2009 by Merkidemis (not verified), 50 weeks 6 days ago
Comment id: 2247

Ok, can someone please cite the crazy people that think getting rid of integration and system testing is a good thing? I have a hard time thinking that such a thing would even cross someone's mind as more then a sick joke lasting all of a second.

Re: Someone crazy

February 17, 2009 by Janusz Gorycki, 50 weeks 6 days ago
Comment id: 2248

Ok, it is not a particular statement per se, dismissing the importance of the post Unit-test QA, that inspired this post. It is rather the general gut feeling I have, that the importance of TDD is blown out of proportions in relation to other means of QA by quite a few evangelists of agile methods.

It is especially aparent in a bunch of marketing-like articles that I have read lately (no links, sorry, let's not spread this nonsense) that you can ONLY be agile if you do TDD, every other QA technique be damned.

Bollocks, I say. TDD is just one of the tools for agile methodology (and not even the most important one), not the nirvana.

BTW: wouldn't you say that threaded comments would be a nice usability addition to this site? This discussion is getting awfully messy, because my responses are not close to the original comments.

System Tests Are Essential

February 18, 2009 by Roger L. Cauvin (not verified), 50 weeks 6 days ago
Comment id: 2249

Unit tests are great for the two purposes you mentioned and not so useful in the other ways you mentioned.

However, you didn't mention one of the most important shortcomings of unit tests. Ultimately, what matters is whether the system solves user and stakeholder problems. In other words, it has to fulfill the requirements. You don't improve what you don't measure. So measure the satisfaction of the requirements, both functional and nonfunctional. I.e., use system tests.

Long response

February 18, 2009 by Chris Wash (not verified), 50 weeks 6 days ago
Comment id: 2250

Very good insights. You need to know both the pros and cons of testing your own code.

I wrote an extended response to this as a blog entry. It morphed very much into its own thing but I'm interested to get your take on the matter.

Thanks very much.

A few notes from this bloke...

February 18, 2009 by Wojtek (not verified), 50 weeks 6 days ago
Comment id: 2251

Duplication has been removed by Artem. Hopefully correctly
I don't want to comment on that post in general, although I think that underrating (and not using) unit tests is much worse that overrating them). Still, like every software development practice, writing unit tests requires your thought and commons sense.

I don't want to comment on that post in general, although I think that underrating (and not using) unit tests is much worse that overrating them). Still, like every software development practice, writing unit tests requires your thought and commons sense.

With regard to the "war story", I would like to deprive it from its value as I believe I am the guy who Janusz refers to in his blog.
1. the "bug" was about poor performance. Everything except for that was still correct. Just users had to wait too long for the answer. Standard (regular) unit tests are not for testing performance, although unit tests frameworks (like JUnit and its derivatives) directly or indirectly support non-unit testing (like integration testing, UI testing or performance testing)
2. The "fix" was about just changing one regexp pattern
"([/\\\\]?[\\S ]*?([^/\\\\]+\\.java))(:\\[?(\\d+)([\\,:](\\d+)\\]?)?)?"
into another one "^(.*?([^/\\\\]+\\.java))(:\\[?(\\d+)([\\,:](\\d+)\\]?)?)?" and I was not able to find with this change (made by somebody else) any automatic unit test (or performance test) which would:
a) prove that the first pattern is slow and that the second is fast
b) demonstrate (document) which new strings would be matched by this new pattern and were not matched by the old one
3. the code in question was not really well tested, as it was an outcome of overnight programming exercise/tournament called "Fedex" by Atlassian. By design its about having something valuable, innovative and/or eye-candy quickly with less (or no) emphasis put initially on the code quality aspects. If the result of Fedex is interesting, then it's always time for polishing it in regular time (and not at midnight). So your suggestions that this code has anything to do with superb unit tests are just invalid.
Having said that, I still wrote it overnight in TDD way (with unit tests written even before the production code) and even though the functionality is quite powerful and flexible, there have been no single bug report (except for the mentioned here performance problem) since I released it in Atlassian IntelliJ Connector several months ago.

Concluding, I would love to hear pros and cons of unit testing (and real war stories) from more developers who really are expert in unit tests and test-friendly design (i.e. they have been using TDD for many years in various software projects) and know they are talking about.

My 2 cents,

Wojtek

I seems that this site liked

February 18, 2009 by Wojtek (not verified), 50 weeks 6 days ago
Comment id: 2252

I seems that this site liked my comment and duplicated its content. ;)
Sorry folks, but I cannot edit it and clean it up.

Cheers,
Wojtek

Test Metrics are only as good as the way they are intrepreted...

February 18, 2009 by Paul Bourdeaux (not verified), 50 weeks 6 days ago
Comment id: 2253

Maybe the Unit Tests aren't lying to you, instead you just aren't listening to what they are really saying. ;)

Unfortunatly I see unit tests and their resulting metrics misused way to much, and I think your blog hit on a lot of the current issues.

For instance, Unit Tests are certainly not meant to replace QA, user acceptance testing, or functional testing. Any development team that believes that they are are most certainly NOT practicing Agile. In fact, the Agile process incorporates product owners directly in the process so that there is continuous user acceptance testing.

Good post.

It's about specification, NOT verification

February 18, 2009 by Mario Gleichmann (not verified), 50 weeks 5 days ago
Comment id: 2257

UnitTests in the sense of TDD are not used for verification (that's a nice side product) but rather for specification (that's what BDD is all about - trying to refocus TDD back into its original purpose anf gettin' rid of all those testing-related vocabulary which produced so much irritations about TDD)

For some further thoughts about TDD as a form of specification (in the 'tradition' of BDD) you may want to take a look at

http://gleichmann.wordpress.com/2007/12/09/test-driven-development-and-d...

and

http://gleichmann.wordpress.com/2008/10/22/did-you-really-get-behaviour-...

Greetings

Mario

I remember

August 16, 2009 by Robert (not verified), 25 weeks 1 day ago
Comment id: 2964

..when I was lucky enough to be working as a developer, the amount of bugs I would miss when testing my own code. I would always enter data I expected people to enter and therefore my code would handle it. sigh Rob

A purpose

September 4, 2009 by Ed (not verified), 22 weeks 4 days ago
Comment id: 3323

I believe every test has its fundamental purpose. Unit tests serves to eradicate some fundamental bugs and ensure that it's compliant with the specs. Although it has its flaws, it is important and eventually upon integration, will serves as a platform for a better user acceptance testing experience.

Cheers, Ed

I know the part about not

October 27, 2009 by Amy (not verified), 15 weeks 17 hours ago
Comment id: 3977

I know the part about not being able to test all possible scenarios really rings true for me. My company has tested and tested many times, over and over, thinking we had a flawless product only to find out that when it gets in to the hands of users they find "creative" ways to break it. I guess the only solution is more testing but it can be frustrating. Amy

TDD is definitely the key practice...

October 29, 2009 by Anonymous (not verified), 14 weeks 5 days ago
Comment id: 4024

...and perhaps Pair Programming ;) Because omitting it is probably the easiest way to see make an agile project degenerate. (Purely her opinion though)

"Unit test are not a necessarily a means for documenting your system.... "
The Angel firmly believes in the documentary power of unit tests. They key reason is that they are executable. This means, if they are running green they are unambiguously telling you the behaviour of the unit under test.

""Green" (all passing) unit tests don't necessarily mean that your system is healthy. "
The Angel is curious what this has to do with unit testing specifically? All testing, absolutely all testing suffers from Russells Paradox. No amount of testing can confirm the system is working correct.

"Trusting your unit test mocks is wrong. "
The Angel has seen far too many developers go nuts with Mock Objects. She agree's this leads to danger and is not always necessary. She thinks it comes from a mistaken belief that a valid unit test must always exercise only the unit and no cooperating objects; this is false.

"They are worthless if they are slow."
The Angel feels she should point out that low execution speed is generally accepted as a property of an agile unit test. So, ipso facto, if its executing slowly it is no longer a unit test.

She also feels your post is suggesting that an agile developer would consider unit tests alone to be sufficient and forgo other important test-froms such as integration, acceptance, user, beta etc.

She hasn't come across anyone who thinks that in well over fifteen years.

Janus, I agree with most of

November 8, 2009 by Gil Zilberfeld (not verified), 13 weeks 2 days ago
Comment id: 4056

Janus,

I agree with most of what you write. It's just that that the conclusion is misleading.
Unit testing is as good as you write them, and allows you reduce wasted time on manual debugging.
If you don't write them well, yes, you might go chasing your tail. But here's the thing - go practice. You'll write better tests and you'll see through the lies.
I've written a post about metric calculation, and what we thought are the best things to measure, so you can actually tell what works in the process. I'll be happy if you can comment your opinion on that.

Thanks,
Gil Zilberfeld
Typemock

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <b> <i> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <br> <blockquote>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters (without spaces) shown in the image.

Best of AgileSoftwareDevelopment.com