Skip to content

Instantly share code, notes, and snippets.

@xpepper
Last active November 20, 2021 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xpepper/5198f863abf6a54ee8119c311cd7a407 to your computer and use it in GitHub Desktop.
Save xpepper/5198f863abf6a54ee8119c311cd7a407 to your computer and use it in GitHub Desktop.
title tags disqus
What is a Unit in Unit Testing?
testing, TDD
pierodibello

What is a "Unit" in Unit Testing?

see the original twitter thread: https://twitter.com/christianhujer/status/1391301843683139585 by Christian Hujer

In unit testing, what's a unit? Is it a method? Is it a class? Is it a module? No. Let's clarify this once and for all.

In unit testing, a unit isn't an element of structure. In unit testing, a unit is an individually observable element of BEHAVIOR.

BTW I use @mfeathers explanation that "unit tests are tests that run fast" as a possible valid (foundation/element of a) definition of the term "unit test".

Stop arguing which element of structure is meant by unit. Unit does not denote an element of structure. It denotes an element of behavior.
And that shouldn't be surprising: Tests are executable specifications of required BEHAVIOR (NOT: STRUCTURE) by example.

So the full definition of unit test is:

Unit tests are fast executable specifications of required behavior by example.

We can, of course, not write unit tests purely on behavior. Behavior is inaccessible without an element of structure that exposes behavior to make it accessible.

An element of structure that exposes behavior to make it accessible is called "interface".

But unit tests should not couple to more structure than necessary. Their means is not to verify structure. Their usage of structure serves only a few purposes:

  • Access behavior for verification
  • Unit interface documentation
  • Decoupling to make them fast
  • Fault injection

Refactoring means a change to the structure of source code without changing the required behavior. The latter is specified by the tests.

Unit tests shall support us with refactoring by providing a safety net so we change structure without accidentally changing required behavior.

Unit tests that are too knowledgeable about structure make refactoring expensive: the more that unit tests know about structure, the more the unit tests have to change as well when we change structure. This is a negative impact in at least two ways:

  • the first negative impact is that refactoring becomes more effort. Not only do we have to - intention - change the structure of the production code, but now we also have to change the structure of the test code.
  • the second negative impact is worse. When we change tests at the same time, and the change is non-trivial, we might, by accident, impact the means of verification of behavior of the test.

Summary

"Unit" in "Unit Test" means unit of behavior (not unit of structure). Structure may change due to refactoring. Keep risk out of refactoring by having unit tests. Keep effort and risk out of refactoring by not coupling your unit tests to structure more than necessary.

Side notes

BTW: Yes, this also means that "Chicago/Detroit" (classicists) wins over "London" (Mockism) when all other parameters are equivalent because mocks introduce potentially harmful coupling to structure, and that makes future change more difficult/expensive.

BTW this also means that a 1:1 association with framework and test style, like "a Cucumber test is not a unit test and a JUnit test is a unit test", is wrong. If you use JUnit but your tests are slow, they are not unit tests. If you use Cucumber, and your tests are fast, they might be unit tests.

Side note: I like to use Cucumber not only for acceptance testing but also for unit testing, especially in those situations where the unit directly implements behavior that I want to describe for or discuss with other humans in pure business language instead of programming.

Kent Beck on this topic

Tests should be coupled to the behavior of code and decoupled from the structure of code.

References and other links

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