๐—จ๐—ป๐—ถ๐˜ ๐—ง๐—ฒ๐˜€๐˜๐—ถ๐—ป๐—ด ๐—ฆ๐—ฐ๐—ต๐—ผ๐—ผ๐—น๐˜€ ๐—ผ๐—ณ ๐—ง๐—ต๐—ผ๐˜‚๐—ด๐—ต๐˜

ยท

3 min read

A unit test is an automated test that verifies a small piece of code quickly and in isolation.

Controversial attributes within this definition are the unit and isolation attributes, controversies are due to these terms being defined differently by unit testing schools.

Two unit testing schools are known as the Classical (aka Detroit) school, the teachings of this school are prevalent in the book โ€œTest-Driven Development: By Exampleโ€ by Kent Beck. The other school is the London (aka Mockist), teachings of this school are found in the book โ€œGrowing Object Oriented Softwareโ€ by Steve Freeman.

๐—ง๐—ต๐—ฒ ๐—Ÿ๐—ผ๐—ป๐—ฑ๐—ผ๐—ป ๐˜€๐—ฐ๐—ต๐—ผ๐—ผ๐—น is based on mocking most collaborators of the system under test, therefore isolation manifests here in the form of isolating the system under test from its collaborators, while a unit is usually identified as a single class; this approach yields several advantages:

๐Ÿญ. Easy identification of areas of failure: The substitution of collaborators with test doubles eliminates them as causes of failure allowing developers to focus on the unit under test to rectify failing tests.
๐Ÿฎ. Convention: As a unit is a single class, it becomes easier to organize and locate test code by creating a corresponding test class for each production class.
๐Ÿฏ. Reduces object-graph complexities: As dependencies are replaced with fakes, we need not concern ourselves with the sub-dependencies of the SUTโ€™s immediate dependencies.

๐—ง๐—ต๐—ฒ ๐—–๐—น๐—ฎ๐˜€๐˜€๐—ถ๐—ฐ๐—ฎ๐—น ๐˜€๐—ฐ๐—ต๐—ผ๐—ผ๐—น teachings specify that tests should revolve around units of behavior, a unit of behavior may be achieved by anything from a single method to a set of classes collaborating together, while isolation is focused around isolating tests from each other by allowing them to run independently from each other and in parallel. This approach presents a number of benefits:

๐Ÿญ. Better resilience to refactoring: The classical school keeps the use of mocking to a minimum and encourages the use of real/production collaborators instead, this means that tests are decoupled from implementation details, you no longer have to verify every method call this way if a method changes within a unit of behavior the test will still pass.
๐Ÿฎ. Easily understood tests: Granularity can make it difficult to understand the bigger picture, therefore focusing on behavior leads to better-understood tests โ€œ๐˜ˆ ๐˜ต๐˜ฆ๐˜ด๐˜ต ๐˜ด๐˜ฉ๐˜ฐ๐˜ถ๐˜ญ๐˜ฅ ๐˜ต๐˜ฆ๐˜ญ๐˜ญ ๐˜ข ๐˜ด๐˜ต๐˜ฐ๐˜ณ๐˜บ ๐˜ข๐˜ฃ๐˜ฐ๐˜ถ๐˜ต ๐˜ต๐˜ฉ๐˜ฆ ๐˜ฑ๐˜ณ๐˜ฐ๐˜ฃ๐˜ญ๐˜ฆ๐˜ฎ ๐˜บ๐˜ฐ๐˜ถ๐˜ณ ๐˜ค๐˜ฐ๐˜ฅ๐˜ฆ ๐˜ฉ๐˜ฆ๐˜ญ๐˜ฑ๐˜ด ๐˜ต๐˜ฐ ๐˜ด๐˜ฐ๐˜ญ๐˜ท๐˜ฆ, ๐˜ข๐˜ฏ๐˜ฅ ๐˜ต๐˜ฉ๐˜ช๐˜ด ๐˜ด๐˜ต๐˜ฐ๐˜ณ๐˜บ ๐˜ด๐˜ฉ๐˜ฐ๐˜ถ๐˜ญ๐˜ฅ ๐˜ฃ๐˜ฆ ๐˜ค๐˜ฐ๐˜ฉ๐˜ฆ๐˜ด๐˜ช๐˜ท๐˜ฆ ๐˜ข๐˜ฏ๐˜ฅ ๐˜ฎ๐˜ฆ๐˜ข๐˜ฏ๐˜ช๐˜ฏ๐˜จ๐˜ง๐˜ถ๐˜ญ ๐˜ต๐˜ฐ ๐˜ข ๐˜ฏ๐˜ฐ๐˜ฏ-๐˜ฑ๐˜ณ๐˜ฐ๐˜จ๐˜ณ๐˜ข๐˜ฎ๐˜ฎ๐˜ฆ๐˜ณโ€ - Vladimir Khorikov

The differences between these schools spills into TDD approaches, allowing either an outside-in approach or an inside-out approach. The liberal use of mocking within the London school means that you donโ€™t have to worry about whether the collaborator's functionality has been defined or not as it is substituted with a fake. In contrast, the Classic school's reliance on real collaborators means that your tests cannot pass until those collaborators have implementations.

Vladimir Khorikov dives into the differences between these schools in his book titled โ€œUnit Testingโ€.

ย