Unit test vs. Developer test vs. Integration test

What are Developer tests? See a clear example of each kind.

David Rodenas PhD
Dev Genius

--

Almost anyone agrees about what is a Unit Test. QA engineers and developers usually give Integration Test different meanings. Extreme Programming defines the Programmer Test concept, whose objective is to create more useful tests. This article outlines the properties of each type of test and creates a common ground to speak about them.

Photo by Mike from Pexels

Unit test

You get the headlamp, place a sensor as a lightbulb, and connect the headlamp to a power source. The test passes if the sensor receives power.

Unit test: the lamp.
  • Runs fast; the scale is milliseconds.
  • Test a unit in isolation; one failure implies one single unit.
  • Mock internal dependencies; replace other components by mocks.
  • Mock externals; avoid databases, network, and external APIs.
  • Failure spots precisely the origin of failure; it is one unit.
  • Refactor is difficult; changes in code usually implies changes in the test.
  • No business value; the test does not explain the objective of the unit.
  • Low confidence; do not test the relation between components.
  • Discourage the use of TDD; test and units are too close.

The test is: does the headlamp powers the lightbulb outlet when it receives power? Complete the Use Case with additional tests for the lightbulb, the switch, the battery, and the wire.

Unit tests have no business value. Probably you are a car factory company, not a headlamp factory company. If you read all the tests, you know which parts you need to build a car, but no idea how to make a car. Changes are hard; if you change any piece, you have to rebuild your tests for that piece, and you do not know how it affects other parts.

Confidence is low. You are not checking if the headlamp socket is compatible with the lightbulb, or if the headlamp glass is black, and it does not allow light to pass; just to name a few.

Developer test

You get the headlamp, a light bulb, a battery, a light switch, interconnect them. Turn the switch on. The test passes if the light bulb emits light.

Developer test: the lamp lights.
  • Runs fast; the scale is milliseconds.
  • Test a business rule in isolation; do not build the whole application.
  • Use internal components; avoid mocks, and use actual parts.
  • Mock externals; avoid databases, network, and external APIs.
  • Failure spots reasonably well the origin of failure; a few units involved.
  • Refactor is easy; the test is resilient to changes in code.
  • Documents the code; connects test and business rules.
  • High confidence; it tests a business rule with relevant components.
  • Use TDD; the most recent edit is vital.

The test is: does turning the switch on lighting the lamp?

Programmer tests have business value. You know what the headlamp does and how it works. Each test becomes a small manual about how to build a car part. You can switch lightbulbs, headlamps, and other pieces, and the test still passes if it works.

Confidence is high. You are not checking each part and also that everything is working well together.

Integration test

You build a car and place it in a dark street. Unlock the door, turn the key, and turn on the light switch. The test passes if it illumines the street correctly.

Integration test: the car lights the street.
  • Faster than human; each test takes seconds or minutes.
  • Test a business rule; imitate the human using the application.
  • Use real internal components; mock nothing here.
  • May use real external dependencies; some mocks are necessary.
  • Failure gives the origin of failure vaguely; consider the whole system.
  • Refactor is hard; test is slow, and failure give vague hints.
  • High business value; document the exact behavior of the system.
  • Highest confidence; the next step is real users.
  • Not suitable for TDD; test-code-refactor cycle is too long.

The test is: does turning the switch on making the car light the road?

These tests are real business value. You know what the car must do. You can change any part and still check if everything works. The problem is that if something fails, you have to debug the full car.

Confidence is the highest. You have a real car. It is also slow because you need to build a new car for each test.

More reading.

If you want to learn more, you can read:

Important quotes.

From Ward Cunningham (2010), from DeveloperTest and UnitTest wiki entries:

A DeveloperTest is the correct name for what the industry generally calls a UnitTest. It is a test written for developers, as distinct from an AcceptanceTest or CustomerTest, written for the OnsiteCustomers.

Under the strict definition, for QA purposes, the failure of a UnitTest implicates only one unit. You know exactly where to search to find the bug.

TestDrivenDevelopment produces DeveloperTests. The failure of a test case implicates only the developer’s most recent edit. This implies that developers don’t need to use MockObjects to split all their code up into testable units. And it implies a developer may always avoid debugging by reverting that last edit.

--

--

Passionate software engineer & storyteller. Sharing knowledge to advance our skills. Join me on a journey of discovery in the world of software engineering.