Skip to content

Instantly share code, notes, and snippets.

@jaycfields
Created July 8, 2014 17:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaycfields/eeddc2ead3fee059cce1 to your computer and use it in GitHub Desktop.
Save jaycfields/eeddc2ead3fee059cce1 to your computer and use it in GitHub Desktop.

Unit Test

The definition of Unit Test is quite general:

In computer programming, unit testing is a method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use. [...] A unit could be an entire module, but it is more commonly an individual function or procedure. --Wikipedia

The above definition states that a unit can be an individual Java method, but it can also be something much larger that likely includes many collaborating classes. Over the years I've found value in splitting my unit tests into two distinct categories - Solitary Unit Tests and Sociable Unit Tests.

Solitary Unit Test

In Java it's common to unit test at the class level. The Foo class will have an associated FooTests class. Solitary Unit Tests follow two additional constraints:

  1. Never cross boundaries
  2. The Class Under Test should be the only concrete class found in a test.

Never cross boundaries is a fairly simple, yet controversial piece of advice. In 2004, Bill Caputo wrote about this advice, and defined a boundary as: "...a database, a queue, another system...". The advice is simple: accessing a database, network, or file system significantly increases the the time it takes to run a test. When the aggregate execution time impacts a developer's decision to run the test suite, the effectiveness of the entire team is at risk. A test suite that isn't run regularly is likely to have negative-ROI.

In the same entry, Bill also defines a boundary as: "... or even an ordinary class if that class is 'outside' the area your [sic] trying to work with or are responsible for". Bill's recommendation is a good one, but I find it too vague. I think Bill's statement is valuable but fails to give concrete advice on where to draw the line. My second constraint is a concrete (and admittedly restrictive) version of Bill's recommendation.

The concept of constraining a unit test such that 'the Class Under Test should be the only concrete class found in a test' sounds extreme, but it's actually not that drastic if you assume a few things.

  • You're using a framework such as Mockito that allows you to easily stub most concrete classes
  • This constraint does not apply to any primitive or Java class that has a literal (e.g. int, Integer, String, etc)
  • You're using some type of automated refactoring tool.

There are pros and cons to this approach, both of which we'll discuss later in the book. For now, it's only important that you understand my definition of Solitary Unit Test, not that you see value in it.

I define Solitary Unit Test as:

Solitary Unit Testing is an activity by which methods of a class or functions of a namespace are tested to determine if they are fit for use. The tests used to determine if a class or namespace is functional should isolate the class or namespace under test by stubbing all collaboration with additional classes and namespaces.

Sociable Unit Test

The definition of Sociable Unit Test is simple: Any Unit Test that contains concrete collaborators and/or crosses a boundary. If you have a Unit Test that's not a Solitary Unit Test, it's a Sociable Unit Test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment