Skip to main content

Side by side

Integration TestvsEnd-to-End Test

What is the difference between an integration test and an end-to-end test?

Updated 3 min read8 differences

In short

An integration test checks that a few components work together, such as code and a database; an end-to-end test runs a full user journey through the whole app.

Integration Test

An integration test is an automated test that checks whether several parts of a system, such as code, a database, and an API, work correctly together.

Read the page on Integration Test

End-to-End Test

An end-to-end test is an automated test that runs a complete user journey through the whole application, from the user interface to the database and back.

Read the page on End-to-End Test

Integration Test and End-to-End Test compared

AspectIntegration TestEnd-to-End Test
ScopeA few components and the connections between themThe whole application, from interface to database
Entry pointA function, module or API endpointThe user interface, through a real or headless browser
EnvironmentOnly the pieces needed, often a database in a containerA full deployment close to production
SpeedMilliseconds to seconds per testSeconds to minutes per test
How manyMany, in the middle of the testing pyramidFew, for the most critical flows
When one failsPoints to a small areaShows a journey is broken, but not exactly where
FlakinessLow to moderateThe highest of all test types
Typical toolsJest, pytest or JUnit, with TestcontainersPlaywright, Cypress or Selenium

The difference, explained

An integration test verifies that two or more parts of a system cooperate correctly: an API route and its database, a service and a message queue, or two services over HTTP. An end-to-end (E2E) test checks a complete task the way a user does it, such as signing up or checking out, usually by driving a real browser through the running application, from the interface to the database and back.

The difference is scope. An integration test calls code or an endpoint directly, sets up only the pieces it needs, often a test database in a container, and checks results such as a response and a new row in a table. An E2E test starts the whole system in an environment close to production and checks what appears on the screen, so it also catches problems in the front end, the configuration and the wiring between services.

That wider reach has a cost. E2E tests take seconds or minutes each, need a full environment and fail more often for reasons unrelated to the change, such as timing or test data. Integration tests are faster and easier to debug, because a failure points to a smaller area. The testing pyramid puts many unit tests at the bottom, fewer integration tests in the middle and a small number of E2E tests for the most critical flows at the top.

A common misconception is that E2E tests can replace integration tests because they cover more. They prove that a journey works, but when one fails it rarely tells you where; a good suite uses both. The terms also blur in practice: an API test that runs against a fully deployed system without a browser is called integration by some teams and end-to-end by others.

Which one should you use?

Choose Integration Test when…

  • You want to check that your code talks correctly to a database, queue or API.
  • You need fast feedback on many cases, including errors and edge cases.
  • You want failures that point straight to the broken boundary.

Choose End-to-End Test when…

  • A flow is business-critical, such as login, sign-up or payment.
  • You need proof that the front end, back end and configuration work together.
  • You want to catch problems only a real browser shows, such as a button that never appears.

Checking an order through the API, and through the browser

Integration Testjavascript
// Integration test: call the route, check the database
test("POST /orders saves the order", async () => {
  const res = await request(app)
    .post("/orders")
    .send({ productId: 7, quantity: 2 });
  expect(res.status).toBe(201);
  const order = await db.orders.findById(res.body.id);
  expect(order.quantity).toBe(2);
});
End-to-End Testjavascript
// End-to-end test: a real browser, the whole app (Playwright)
test("a customer can place an order", async ({ page }) => {
  await page.goto("/products/7");
  await page.getByRole("button", { name: "Add to cart" }).click();
  await page.getByRole("link", { name: "Checkout" }).click();
  await page.getByRole("button", { name: "Place order" }).click();
  await expect(page.getByText("Thank you for your order")).toBeVisible();
});

Readers ask

Is an API test an integration test or an end-to-end test?

It depends on the scope. A test that calls one service backed by a test database is an integration test; a test that goes through every deployed service the way a client would is closer to end-to-end, just without a browser.

How many end-to-end tests should I have?

Few: enough to cover the journeys that would hurt most if broken, such as login and payment. Everything else is cheaper and more reliable to check with unit and integration tests.

Should integration tests mock external services?

Mock what you don't own, such as a payment provider, and use the real thing for what you do own, such as your database. Testing that real connection is the point of an integration test.

More

Settings