Testing software: unit, integration, end-to-end in plain terms
Three kinds of automated test, what each catches, and why a project needs all three in the right proportions.
The short answer
Software is tested at three levels, and a project needs all three in the right proportions. Unit tests check one small piece of logic in isolation: does this function calculate the discount correctly? They are fast, precise and numerous. Integration tests check pieces working together with real dependencies: does saving an order actually write to the database and send the confirmation? End-to-end tests drive the whole application the way a user would: can a customer sign up, book and pay? Each level catches what the others miss. The healthy shape is many unit tests, a solid set of integration tests and a small number of end-to-end tests on the flows that matter most, all running in the pipeline on every change.
The three levels
| Level | What it tests | Speed | Catches | Misses |
|---|---|---|---|---|
| Unit | One function or component alone, with everything else faked | Milliseconds; thousands per minute | Logic errors, edge cases, regressions in calculations | Whether pieces are wired together correctly |
| Integration | Several pieces with real database, queues and services in test mode | Seconds each | Wiring errors, query mistakes, contract mismatches with services | The full user journey and the interface |
| End-to-end | The whole application through the browser, as a user | Minutes each | Broken flows, interface errors, things that only fail when everything runs together | The precise cause; they say what broke, not why |
The healthy shape
- Unit tests for every piece of logic that could be wrong: calculations, validations, permissions, formatting. Many, fast, run constantly.
- Integration tests for every boundary: each database operation, each external service, each queue, with real test instances.
- End-to-end tests for the critical flows only: the five to ten journeys that would hurt most if broken, run on a preview before release.
- All in the pipeline: a failing test blocks the change.
- A test for every bug fixed, so it cannot return.
What it means for the business
Changes ship with confidence. A regression is caught by a machine in minutes rather than by a customer in a week. New developers can change code they did not write, because the tests tell them what they broke. And the cost of change stays flat over years instead of climbing, which is the difference between software that evolves with the business and software that everyone is afraid to touch.
What this means for you
Expect your software to have tests at all three levels, in a pyramid: many fast unit tests, real integration tests at every boundary, a few end-to-end tests on the flows the business depends on, all run automatically on every change. It is what keeps the second year of a system as fast and safe to change as the first, and it is the difference between software you own and software you are afraid of.
Frequently asked questions
Why not just test everything end-to-end, like a user would?
Because end-to-end tests are slow, fragile and poor at telling you what broke. A suite of hundreds takes an hour and fails for reasons unrelated to the code. Unit and integration tests are fast and precise; they find the cause in seconds. End-to-end tests are reserved for the handful of flows where the user's experience is the thing being protected: sign-up, checkout, the core task.
How much testing is enough?
Enough that a change to any part of the system is checked automatically before it ships, and that the flows the business depends on are exercised end-to-end. Coverage percentages are a weak proxy; the question is whether the things that would hurt if broken have a test that would notice. A thin suite on the critical paths beats a thick one on trivia.
Does testing slow development down?
It slows the first version slightly and speeds every version after, because changes can be made with confidence instead of fear. Projects without tests slow to a crawl after a year, when every change risks breaking something nobody remembers. The tests are what keep the second year as fast as the first.