Integration Testing in Software Engineering: Types, Process & Strategies
Your login works. Your order module works. The payment module also works. But what happens when all three have to work together? That is the problem integration testing helps us find.
Integration testing checks whether two or more connected software parts exchange data and work together as expected. It focuses on their interfaces and interactions: for example, whether an order service sends the right amount to a payment service and correctly handles its response. A component may pass its own tests and still fail when connected to another component.
Open the chapter map
In Chapter 26 on unit testing, we checked individual functions and modules. Now we connect them. A student often asks: “If every module has already passed, why test again?” The answer is simple: a working part does not prove that the connection is working.
What is Integration Testing in Software Engineering?
Integration testing is a software testing level where related components, modules, services, or systems are combined and their interactions are checked. The main test target is the boundary between them: the information one part sends, the information another part expects, and what happens when something goes wrong.
Think of two students passing a message. The first student may write correctly and the second may read correctly, but if one writes in a format the other cannot understand, communication fails. Software modules face the same issue.
Both modules may work alone. Their shared contract can still fail.
Integration testing fits into the wider software testing levels and process. It is often performed after useful component checks are available, but teams can integrate small parts continuously instead of waiting until all development is finished. The exact sequence depends on the project and its development approach.
Objectives of integration testing
Check data exchange
Verify fields, values, formats, and meaning across the boundary.
Check combined action
Confirm that one component uses another component's result correctly.
Check error handling
See what happens when a dependency rejects, times out, or returns bad data.
Find boundary defects early
Locate an interaction problem before it grows into a full system failure.
Understand Integration Testing with One Easy Example
Imagine a college admission website. A student fills a form, uploads documents, and pays a fee. The application has three parts:
- Form service validates and saves the application.
- Payment service handles the fee transaction.
- Receipt service creates a confirmation after successful payment.
Separate tests show that each part can do its own job. Integration tests check the journey between them. Does the form service pass the right application ID? Does the receipt service create a receipt only after confirmed payment? If the payment fails, is the application still marked “unpaid”?
Application ID
Status + amount
Receipt ID
Test the value and response at each arrow, including failure paths.
The important lesson is that integration testing is about more than “the screen opened”. We must check what data crossed each boundary and what state was saved.
What Problems Can Integration Testing Find?
Many integration defects arise because two teams or modules make different assumptions about the same interface. A clear documented and testable requirement helps define the expected result before a test is written.
| Boundary problem | Admission website example | Useful test |
|---|---|---|
| Wrong field or format | Payment expects applicationId; form sends app_id. | Send a real request and verify the received ID. |
| Wrong value or unit | Fee is stored as paise but treated as rupees. | Assert the exact amount at both ends. |
| Missing failure handling | Payment fails, yet the receipt is generated. | Force a declined payment and inspect saved state. |
| Timing issue | Receipt is requested before payment confirmation arrives. | Delay the response and check ordering. |
| Configuration mismatch | Test service points to the wrong database or endpoint. | Run with controlled test configuration. |
| Duplicate request | A repeated callback creates two receipts. | Send the same callback twice and check the result. |
On a phone, swipe the table sideways to see every column.
These examples also show why coupling and clear module interfaces matter. When modules depend on each other's hidden details, a small change can break their integration.
Types and Scope of Integration Testing
Books sometimes use “types” to mean test levels, sometimes integration strategies, and sometimes tools or methods. Keep these ideas separate in your answer.
Component integration testing
Checks interfaces and interactions among components of the same system. Example: application service, payment adapter, and database repository working together.
System integration testing
Checks interfaces between separate systems. Example: a college portal exchanging payment status with an external payment system.
In many university syllabi, both are simply discussed under integration testing. Modern testing terminology distinguishes them. The ISTQB Foundation Level syllabus is a useful reference for testing levels; your semester answer should still follow the terms used by your course.
Manual and automated describe how checks are executed. API, database, and message queue integration describe where a boundary is tested. They are useful practical descriptions, but they do not replace the two integration scopes above.
Main Integration Testing Strategies
Strategy means which parts are connected first and in what order. This affects when a defect is discovered and how easily we can identify its source. The traditional exam strategies are big bang, top-down, bottom-up, and sandwich (hybrid).
1. Big Bang Integration
All major modules are connected together first, and then the combined product is tested. Setup may look simple for a very small system, but if a test fails, the faulty connection can be hard to locate. Waiting for every module also delays feedback.
2. Top-Down Integration
Start with a higher-level module, then connect its lower-level modules step by step. The main flow can be checked early. When a lower-level module is not ready, a stub can provide a controlled response temporarily.
Early tests cover the upper control flow; real lower components replace stubs as they become ready.
3. Bottom-Up Integration
Start with lower-level modules and combine them into larger groups. This gives early confidence in foundational services. If the higher-level caller is not ready, a driver can call the lower module and supply inputs temporarily.
Foundational interactions are checked before the full upper flow is available.
4. Sandwich or Hybrid Integration
Top-down and bottom-up work proceed toward the middle, where the parts are joined. This can be useful in a larger layered system, but the meeting point and temporary test support need planning.
| Strategy | Order | Temporary support | Main trade-off |
|---|---|---|---|
| Big bang | Connect most parts at once | May use none for the complete set | Failure source is difficult to isolate. |
| Top-down | Higher to lower | Stubs for missing lower modules | Lower details are tested later. |
| Bottom-up | Lower to higher | Drivers for missing higher callers | Full user flow appears later. |
| Sandwich | Both ends toward the middle | Stubs and drivers as needed | Coordination is more complex. |
On a phone, swipe the table sideways to see every column.
Practical point: Modern teams often connect small, ready pieces frequently and run automated checks after changes. This is an incremental way of working. “Continuous integration” refers to regularly merging changes and checking the shared build; it is not another name for the integration testing level.
Stub vs Driver: The Easiest Way to Remember
A stub replaces a component that the code under test would call. A driver replaces a caller that would call the code under test. Both are temporary test support, not the real missing component.
Stub
The order service calls a payment service that is not ready. A stub returns a fixed response such as “payment approved”.
Memory: Stub sits below the caller.
Driver
The payment module is ready but the checkout page is not. A driver calls the payment module with test inputs.
Memory: Driver drives the call from above.
Important limit: A stub can make a test predictable, but it cannot prove the real payment provider works. Add a separate test with the real integration or its safe test environment when that boundary matters.
Integration Testing Process: Step by Step
There is no need to start with random button clicks. Use the interfaces and expected behaviour from requirements and design. The SDLC chapter explains where building and testing activities fit in the whole software project.
List the modules or systems that will communicate. Draw who calls whom and where data moves.
Write the input format, valid response, error response, state change, and relevant time limits.
Decide whether you are checking component or system integration and whether parts will be joined incrementally.
Use test accounts, known records, suitable versions, and safe test endpoints. Reset data between repeatable tests.
Check successful exchange, invalid or missing fields, rejection, timeout, retry, and duplicate events where relevant.
Run each case; compare actual request, response, saved state, and logs with expected behaviour.
Confirm the original defect is fixed and that the change has not broken connected workflows.
Keep results, defect references, unresolved risks, and the version tested.
In a small project one developer may write and run these tests. Larger teams may share the work among developers, testers, and people responsible for external systems. Responsibility depends on the project; the goal remains the same.
Worked Example: Admission Fee and Receipt
Requirement for this example
After a confirmed fee payment, the admission application becomes “paid” and receives exactly one receipt. A failed payment must not produce a receipt.
Unpaid
Success or failure
Paid + one receipt, or unpaid
Now design tests around the boundary, not only around the page appearance:
| Case | Input or event | Expected result across modules |
|---|---|---|
| IT-01 · Success | Valid application ID, correct fee, confirmed payment. | Status becomes “paid”; exactly one receipt uses the same application ID and amount. |
| IT-02 · Decline | Payment returns “declined”. | Status stays “unpaid”; no receipt is created. |
| IT-03 · Timeout | Payment response does not arrive within the defined limit. | No false success; the system records a pending or failed state according to the agreed design. |
| IT-04 · Duplicate callback | The same confirmed payment event arrives twice. | One paid application and one receipt; no duplicate record. |
| IT-05 · Wrong ID | Payment response belongs to a different application ID. | Current application is not incorrectly marked paid. |
On a phone, swipe the table sideways to see every column.
The exact timeout status depends on the project's requirement. A good test does not invent its own business rule; it checks the rule the team has agreed to implement. For an external payment provider, use its sandbox or approved test environment so the test does not create real charges.
A small test record
Test ID: IT-02 Boundary: Payment → Admission → Receipt
Precondition: Application A101 exists with unpaid status; no receipt exists.
Action: Send a declined payment result for A101.
Expected: A101 remains unpaid and the receipt count remains zero.
Evidence: Saved application status, receipt count, and relevant response or log.
Unit vs Integration vs System Testing
These levels answer different questions. They complement each other; one level does not guarantee that the next level will pass.
| Level | Main question | Admission website example |
|---|---|---|
| Unit / component | Does one small part work as intended? | Does calculateFee() return the correct amount? |
| Integration | Do connected parts exchange data and work together? | Does payment confirmation update the correct application and trigger one receipt? |
| System | Does the complete system satisfy its specified behaviour? | Can a student complete the admission journey through the complete application? |
On a phone, swipe the table sideways to see every column.
Integration tests may cover a substantial flow, and the boundary with system tests can depend on the system architecture and test objective. The key is to state what is being checked, not just what label the team gives the test.
Benefits, Limitations, and Common Mistakes
Why teams use it
It finds mismatched contracts, incorrect data flow, error handling gaps, and state problems before a complete user journey depends on them.
What it cannot prove alone
It cannot prove every unit path, every user experience, or every production condition. Test doubles can hide faults in the real dependency.
Keep it repeatable
Use stable test data, clear expected results, controlled environments, and cleanup so one test does not affect the next.
Avoid these mistakes: testing only happy paths, using an uncontrolled live service, asserting only the HTTP status while ignoring saved state, forgetting duplicate or delayed events, and calling every automated test an “integration test”. A test is identified by what interaction it checks, not merely by the tool that runs it.
Integration tests provide useful evidence for software quality assurance and validation, but test results should be read together with requirements, reviews, other test levels, and remaining risks.
How to Write Integration Testing in an Exam
2-mark answer
Integration testing is a software testing level that checks interfaces and interactions between connected components or systems. It verifies that they exchange correct data and work together as expected.
5-mark answer structure
- Write the definition and purpose.
- Explain why unit tests alone are insufficient.
- Give one interface example.
- Name top-down, bottom-up, big bang, and sandwich strategies.
- Mention a stub and a driver briefly.
10-mark ready answer
Integration testing checks how connected software components or systems interact after their individual behaviour has been checked. Its main focus is the interface between parts: data passed from one module to another, the format and meaning of that data, the order of calls, returned responses, error handling, and changes in stored state.
For example, in an admission website, the application service sends a fee request to a payment service. After a confirmed payment, the application should become paid and one receipt should be created. If payment fails, the application should remain unpaid and no receipt should be issued. Each service may pass its own unit tests while this combined behaviour still fails.
In component integration testing, interactions between components of one system are checked. In system integration testing, the interaction between separate systems is checked. Teams choose an order for joining the parts. Big bang joins many parts at once but makes faults harder to locate. Top-down starts with higher modules and may use stubs for missing lower modules. Bottom-up starts with lower modules and may use drivers for missing callers. Sandwich combines top-down and bottom-up work.
The process includes identifying boundaries, defining expected behaviour, preparing the environment and data, designing positive and negative test cases, executing tests, recording defects, retesting fixes, and running regression checks. Good cases cover success, invalid data, rejection, delay, and duplicate messages where relevant. Integration testing helps find communication faults early, but unit, system, and acceptance tests are still needed for their own objectives.
Quick Revision and Memory Trick
Four-question shortcut: SEND — Sent the right data? Errors handled? Next action correct? Data saved correctly? Use SEND when you design a test for any module connection.
Frequently Asked Questions
When should integration testing start?
Start when two connected parts and a clear expected interaction are available. You do not have to wait for every module in the application to be complete.
Is integration testing done only after unit testing?
Unit checks commonly provide a useful base, but iterative teams may build and run integration checks as connected components become ready. The important point is to know what has been checked and what has not.
What is the difference between a stub and a driver?
A stub stands in for a component being called. A driver stands in for a caller. Top-down testing commonly uses stubs; bottom-up testing commonly uses drivers.
Is API testing always integration testing?
No. An API can be tested at different levels. It is integration testing when the test checks a meaningful interaction between connected parts or systems.
Does integration testing replace system testing?
No. Integration testing focuses on interactions at chosen boundaries. System testing checks the behaviour of the complete system against its specified requirements.
Conclusion
Integration testing answers a practical question: can the parts of our software work together correctly? Connect a small set of components, define what must cross their boundary, test both success and failure, and inspect the final state. For exams, remember the four traditional strategies and the stub–driver difference. For real projects, remember that the most valuable result is finding a broken connection before students or customers depend on it.
