cwash into software

Don’t Unit Test Anymore… No, Really!

by Chris Wash on Feb.17, 2009, under Developer Testing, Java, Software Engineering

I just read Your Unit Tests Lie to You by Janusz Gorycki and I was going to leave a comment there, but thought it was more appropriate to expand my comments off into their own thing.  For those that haven’t read the article, its basic premise is to grab hold of the nearest “test infected” reader and shake the warm and fuzzy out of them.  It paints the short sightedness of many recent “unit testing” converts as living in a dream world where unit tests should replace formal testing. It follows with many sentiments I’ve read (and written about here) for a while now.  It’s not that I disagree with what is being said in the article, or its tone for that matter; most of what is being said is spot on.  Unit testing is definitely not a silver bullet.  If you read my blog often, you no doubt get that. The article ends:

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

So to Janusz, the fundamental problem here is a general ignorance of the purposes behind a unit test suite.  I agree 100% that’s the primary factor behind his problem.  What don’t we agree on?  Semantics.  But semantics are important!  How far do we have to go for a true zen-understanding of this issue?  Not far.  Indulge me —

When is A Unit Test is not a Unit Test?

Here’s my thesis: you may use a unit testing framework, but what you write are developer tests.  Even if they are technically unit tests, it is against everyone’s interest to call them this.  Picky, useless distinction, you say?  Hear me out.

There is a vast difference between the gamut of possible automated tests one could write and what is known colloquially as a unit test.  A number of different kinds of automated tests are written against frameworks that are built on top of unit testing frameworks.  That doesn’t make them unit tests.  It doesn’t make sense to call them unit tests.  A square is a rectangle, but does that make every rectangle a square?  An automated acceptance or integration test is subject to a completely different set of problems (in areas such as specification, maintenance, complexity) than a unit test.  In fact, about the only thing they share is their lifecycle and execution model, which many times has been retrofitted into the JUnit lifecycle and execution model.

“Unit Testing” and Linguistic Drift

I’ve recently seen a number of different incarnations (1, 2, 3) of the argument that we should eschew use of the term “best practice” because of the implications of its linguistic drift and general propensity of people to turn off their brains when just spoon-fed answers, not having to experience deriving the solution for themselves.  Similarly, the popularity of unit testing frameworks and the sheer frequency with which the term has been used have, in a sense, set the idea of developer testing back considerably.  Cedric Beust makes the point that in many cases we’ve confused [developer] testing terminology with JUnit terminology, and TestNG was in part a response to that.  Here we oversimplify the problems we choose to bite-off and the goals we strive toward.  They’re not realistic.  Is it no wonder so many people fall flat when trying to adopt “unit testing”?

While there may be some overlap with the goals of validation and verification, most in the know consider the true benefits of “unit testing” to be a totally different animal altogether.  We seem surprised to find the benefits of doing developer testing have little to do with what “testers” do.  This dischord causes a lot of confusion, and has sparked a lot of articles.  Some draw this conclusion, appropriately, that developer testing, while it fits a rigid definition of what testing is, shares little with what a typical “tester” is responsible for (true V&V).  Quite often developers are the only ones doing any automation work, including this automated “developer” testing.  Developers tend to do it for all kinds of different reasons, too.  We’ll use a suite of automated tests to proceed without fear of integration errors.  That adds value totally independent of validation and verification practices.  If our suite catches regressions before we hand a single version off to testers, that saves both developers and testers time.  I could go on and on, but the term “unit testing” conveys very little of these kinds of benefits to the development lifecycle, and as it turns out, causes a great deal of confusion.

The Right Usage

When we’re talking pure unit tests, that is, black-box testing components in pure isolation (which requires isolated dependencies), not in concert, as developers we can certainly find merit in this practice.  But what we’ve learned is that this idea of unit testing, while quite beneficial as a development practice, shares very few goals with “testing” as we know it from a classical definition of the word (end-to-end V&V).  Perhaps a few years ago this distinction was not that true, but we now know better.  We know the danger in trying to bend unit tests into something they’re not.

My point is essentially this: knowing how to use a unit testing framework, a very simplistic construct on the surface, to do all of these wonderful things is certainly not something that just “falls out” of developing a unit of code – it’s not something we should expect developers to just deliver each iteration as part of their deliverable like it’s “done.”  Effort invested to develop and maintain test code alongside the code under test is not free.

Only if you are persistent will you come to understand there sometimes is very little benefit in terms of “full blown”, classical validation and verification – the whole reason you set out on this crazy “unit testing” kick. You either stick with it, or write it off at this point.  If you stick with it,  well, I’ll save you the trouble of figuring this out for yourself; you learn it’s only another development practice, that needs to be balanced out with other sound practices. It’s hard work.  Really hard.

Then why go to all the trouble?  It’s my contention, and I assume most will agree, that developer testing is useful.  It drives out better designs, code, and has the potential to thwart a caste of would-be regressions.  It can stamp out integration errors.  It can help you learn about a new framework or prototype a new feature.  But that usefulness comes with a very real cost.

If we truly acknowledge that the type of practice we’ve talked about has merit as a development process, it makes very little sense to continue referring to the practice as “unit testing.”  If testing modules of code, driving development with these tests, maintaining them alongside the code, and other automation activities are worthy practice for developers, we should consider the semantics of our vocational vocabulary.  Let’s stop confusing each other.  We’re not talking about delivering 100% code coverage, we’re not talking about replacing testers (unless you’ve got the huevos to go without them, anyway), and we’re surely not talking about writing or releasing bug-free software.  It’s a lot easier to cut through a lot of the hype and confusion if we can all learn to say developer testing and understand it as such.  Let’s put the term “unit test” to rest.

R.I.P. unit tests.  Long live “developer tests!”

More Related Content

:, , , ,
6 comments for this entry:
  1. Janusz Gorycki

    I think you may actually be right that we should just stop using the term “unit tests”, because the meaning of this term has been twisted and distorted to pretty the point where it lost its original meaning. Re-badging it to “Developer tests” could be beneficial, as it better describes what these tests are for. Also – it makes it clear that these tests are a natural part of what every developer has no choice but do anyway when they write code, regardless of whether they do TDD or not – it is just that if you don’t use automated testing frameworks for the purpose, you end up doing it all manually, and likely with worse results.

  2. Joerg

    My understanding always (at least since my studies in the nineties) has been, that “unit tests” are tests against isolated sofware units (ie. modules or functions). These are usually created and executed/scheduled in regression by developers. The concept is older than the popular frameworks.
    Nevertheless, I think you should not confuse unit testing (which are developer practices) with QA tests of a software as a whole (end-to-end if you like).
    Both are necessary, if you want your software to reach a certain degree of quality. I’d recommend to also add integration testing to your software process – this makes for higher quality test candidates for the QA as it allows combined testing of a whole bunch of units in concert.
    By the way, the QA role in some cases might be very well made up of members of a developers team. So the term “developer test” can be just as misleading or ambiguous. Just my 2 ct.

  3. Kevin Hazzard

    Semantics are important but I would be happy to just get the average developer into a testing mindset. Most organizations, if they make the mistake of displacing integration and system testing with just the tests that developers write, will come back to their senses eventually. And the unit-test-only bigots who led them down that primrose path will mature.

    Honestly, though, I’m not worried about the semantics or the test-happy developers. Having test-happy developers is a good thing, even if they don’t yet understand what they are doing because they have the right idea (and maybe the wrong execution). I’m worried that we’re a solid decade into understanding the best practices for unit testing and the majority of developers I come into contact with don’t have a clue how to how to build developer based testing into their methodology. And I’m not even a TDD extremist. I’ll settle for TED (Test Eventually Development).

  4. dlm

    I used to do write software and do software test, long ago, for a company whose bread and butter at that location was Independent Software V&V. We had thick, detailed books of requirements to test against. After a while it became obvious what an inefficient thing it was, to write software, THEN test it. Shouldn’t the things it was going to have to be able to do be foremost in your mind as you were writing the code? Prevent errors, instead of catching them? When I started reading about TDD and unit testing, it sounded like exactly what we’d been thinking of. With all the same issues of misinterpreting requirements, miscoding, and partitioning the problem – 2X. Still sounds good, though, to at least be defensively focusing on the requirements when you start to write.

  5. bob

    TDD is a joke. Make it stop.

  6. Gregory Kornblum

    You definitely have something there when you mention the fact of how doing these “tests” relate to cost. Spending the man hours bending your development to follow the “rules” of unit testing is costly. I have always tested my development as soon as I had something to the point of where it can be tested and eventually full end to end testing in the past 13 years. In the end I have achieved the same results and spent much less time doing so. I continue to do so and save the company money to be spent on bigger and better things. I also use my own brain and not follow along like the rest of the sheep. Nowadays it seems the programmers are being programmed.

Leave a comment

GoogleYahooWordpressAOLFlickrBloggerLivejournalMyOpenIDTechnoratiVerisignVidoopClaimIDOpenId



Enter your comment

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...

Archives

All entries, chronologically...