Schedule and Events



March 26-29, 2012, Software Test Professionals Conference, New Orleans
July, 14-15, 2012 - Test Coach Camp, San Jose, California
July, 16-18, 2012 - Conference for the Association for Software Testing (CAST 2012), San Jose, California
August 2012+ - At Liberty; available. Contact me by email: Matt.Heusser@gmail.com

Thursday, June 05, 2008

So ... What, exactly, is a unit test?

A popular testing magazine has asked my collegue, Chris McMahon, and myself, to write an article defining terms in unit testing.

Of course, the biggest term of all for that article is probably "unit test." I've been thinking about that today, and I would like your help.

What do you think?

5 comments:

Raoul Duke said...

(Why do I feel like posting here is taking a step into the jaws of defeat?)

For me, a unit test is something pretty small which exercises some basic functionality of a system. I prefer the tests to err on the small and succinct side.

The purpose of it is to sanity check the code I already wrote, and the code I might some day change. By sanity check I mean not only find bugs, but also give me a chance to use it as a customer - sometimes I suddenly see how the API should be different to be better for users, something I would otherwise have missed.

The question of how atomic or separable or isolated or whatever a given unit test is is not something I have a solid definition or dogma about, just feelings.

Is that at all what you are asking about? I mean, that all feels pretty vanilla. I could go quote the folks who invented unit testing, or the folks who currently are top google hits when you search for "unit testing", but you can do all that, hence my personal take on it.

What are your thoughts which led to your question?

yours sincerely.

Shrini Kulkarni said...
This comment has been removed by the author.
Jason said...

Jaws of defeat? Nonsense! There is no defeat in testing! Just new information :)

I think what Raoul described is relatively close to what most people think of as a unit test: a test that covers a relatively small bit of functionality, usually a single method or function. A more literal translation, though, might bring some interesting points.

Princeton's wordnet has several definitions, including:

A unit of measure.
A building block.
An assemblage of parts.

Each of those definitions would change the possible scope of a unit test. For example, if we accept a unit as any measurable quantity of code, you could unit test every 100 lines of code. Or an individual block of code (e.g. in Perl, defined by curly braces). Units as building blocks could lead to testing functions or methods, as we're comfortable doing. Testing an assemblage of parts might include testing a function that relies on several other functions, testing fully-assembled applications, or maybe an API like Raoul mentioned.

I enjoy taking a liberal view of the definition of "unit" when it's useful to me. Ah, that's a key word isn't it: USEFUL.

I think, to distill all that and some other unwritten (unfinished) thoughts down, my definition would look something like this:

"A repeatable action that reveals a useful declaration about the state of a defined part or conglomerate of parts."

Jeff said...

I think "unit test" is a bit more fine-grained (or "atomic", if you like) than that:

A unit test executes a single logic path through a public (in the OO sense) functional unit (e.g., class method) and proves that the state of the code artifact under test meets assumptions specified within the test.

Likewise, a code artifact has been completely unit tested if and only if all logic paths through said artifact can be proven to have been tested by a collection of unit tests, and all state information accessed and/or modified by that artifact has been proven to be as expected at the conclusion of each test.

Finally, three points: Any non-constant properties or other state information of the artifact under test which are not modified by any unit test in a suite which tests all logic paths, is a defect which should be removed. Any constant value which is not accessed by any test, is a defect which should be removed. (It is quite common to discover that such a constant is used by outside, client, artifacts which will fail their own unit tests when said constant goes missing. To repair that test failure, add back the constant in question and add a test to the containing artifact to prove that the constant is set properly.) And, last but not least, any logic path or internal method which are not executed by a collection of tests which successfully verifies all externally visible state changes function as expected, is a defect and should be removed.

Don't repeat yourself, and do listen to Antoine de Saint-Exupery: "A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."

Ainars Galvans said...

I think „unit testing” is the biggest term indeed. Because unit may be anything starting from user story and ending with a piece of code that has no dependencies on other code. I’ve seen so different usage of this term depending on company, project or even context in which it is used… Sometimes it is even used synonymous to “developer testing” or API-level testing.
Maybe this is only my strange/bad experience. Anyway I think writing a good article on this topic is a real challenge. I would suggest you to research the history of the term (and associated terms such as component testing). I didn’t myself but here are some thoughts: I think that it’s original idea (and the name unit in it) is outdated thanks to mocks, stubs, library usage, modeling/code generation tools. Not to mention the impact that XP, TDD and Agile in general had on the term and its popularity.