CodePark/ questions / Strategy & the test pyramid
START PRACTICINGPRACTICE
Backend question · Backend testing › Strategy & the test pyramid

For a Node/NestJS backend, what is the difference between unit, integration and end-to-end tests, and how would you balance them?

Unit tests check one piece of logic, integration tests check your code with a real dependency, and end-to-end tests check the whole running system from outside. Balance them by risk.

A unit test checks one piece of logic, such as a service method or a pure function. Its collaborators (the other classes it calls) are replaced by test doubles: fake versions that you control. A unit test runs in milliseconds. When it fails, it points straight at the problem.

An integration test checks your code together with a real dependency. Examples:

  • a repository against a real Postgres database
  • a cache layer against a real Redis
  • a controller called through the HTTP layer, with a real database behind it

Integration tests catch bugs that mocks hide: SQL bugs, mapping bugs, transaction bugs and configuration bugs.

An end-to-end (e2e) test drives the running system from the outside, over HTTP and across services, the same way a client would.

Balance them by risk:

  • Write unit tests for real business rules.
  • Write a solid layer of integration tests for every boundary you own: the database, queues and HTTP.
  • Write a few e2e tests for critical user journeys, like signup and checkout. Keep them few, because they are slow and the most likely to be flaky (pass or fail at random).
  • A unit test checks one piece of logic, with its collaborators replaced, and runs very fast.
  • An integration test runs your code with a real dependency, such as Postgres or Redis.
  • An end-to-end test drives the running system from outside, the way a client would.
  • Balance the tests by risk and cost, and keep only a few e2e tests for critical journeys.