Balance between
quality and deadlines

Integration Testing

One module works - great. Another works - awesome. Together, they should work even better. But in practice, things don’t always go that way. This is where integration testing comes into play, checking how parts of the system interact with each other.

adapter

What is Integration Testing?

Integration Testing is the stage of testing where the interaction between modules, components, or external systems is verified.

If a unit test is like checking the parts of an engine, then integration testing is like checking if the car actually starts when everything is assembled.

Why is it needed?

Individual modules may work perfectly, but errors often appear at the boundaries between them:

  • Problems with data formats, timing, dependencies
  • Errors due to different versions of libraries, APIs, protocols
  • Instability when interacting with external services

Integration testing helps detect defects in interactions, not in individual components.

When is it performed?

  • After unit tests
  • After assembling several related modules
  • When working with external APIs, databases, or message brokers
  • After changes in connecting code or contracts between modules

Examples of integrations worth testing

  • Frontend ↔ Backend (REST API, GraphQL, etc.)
  • Service ↔ Database
  • One microservice ↔ Another microservice
  • Backend ↔ External payment gateway
  • Service ↔ Message queue (Kafka, RabbitMQ)
  • Backend ↔ Email service, S3, Auth providers

Types of Integration Testing

Big Bang
All modules are assembled and tested at once. Simple, but difficult to localize errors.

Incremental
Modules are added gradually, with interactions tested at each step.

  • Bottom-Up: from low-level components to high-level ones
  • Top-Down: from the interface to internal modules
  • Sandwich: a combination of both approaches

How are integration tests written?

  • A real or emulated environment is set up
  • Dependencies are brought up (real or mock services)
  • A set of tests is run that:
    • Sends requests between modules
    • Verifies interaction correctness
    • Validates data, errors, timeouts

Tools:

  • pytest + requests + docker-compose
  • Go + TestContainers
  • SpringBootTest
  • Postman + Newman
  • Jest + supertest (Node.js)
  • Playwright / Cypress (UI + API)

How does it differ from unit and system testing?

| Test type        | What is checked             | Environment          | Speed   |
|------------------|-----------------------------|----------------------|---------|
| Unit test        | Individual function/method  | Local, isolated      | Fast    |
| Integration test | Component interaction       | Service + service    | Medium  |
| System test      | The entire system           | Almost production    | Slow    |

What can go wrong without integration tests?

  • Broken API contracts between modules
  • Incorrect data format or structure
  • Serialization issues
  • Timeouts, race conditions, conflicts
  • Subtle production bugs that don’t reproduce locally

Useful tips

  • Don’t test everything through the UI - it’s faster and more reliable to run integration tests at the API or code level
  • Use a dedicated test environment
  • Mocks are useful, but tests with real services are more important
  • Build a CI pipeline where integration tests run separately from unit tests
  • Don’t forget logs and debugging - when failures happen, it’s important to see both sides of the interaction