Unit Testing vs Integration Testing
Among the different levels of software testing, this article discusses the difference between unit testing and integration testing.
Software testing is an inescapable aspect of the software development life cycle (SDLC). It involves finding potential errors and bugs in a software product and verifying whether it is in compliance with quality standards and end-user requirements. It helps deliver scalable, high-quality, fully-functional products within the given deadline and budget.
For example, you created an API in an E-commerce app that takes the input of the product’s ID and returns its details. However, what if the product with the entered ID does not exist? Here, the users must receive a specific error message. There are many other scenarios that you must check before releasing the product.
To validate every functionality of the product, a test case comes in handy. It is a collection of actions performed on a software product to evaluate its particular feature and check whether it functions as expected.
A single software product undergoes four levels of software testing, from testing individual components to testing the product as a whole. These levels are as follows:
- Unit testing: Tests each software module individually.
- Integration testing: Integrates individually tested units logically and, later, evaluates the interaction or communication between those units.
- System testing: Tests a complete software product.
- Acceptance testing: Some users or an internal team tests the product for its correctness.
According to these levels of testing, testers perform different types of tests. Today, in this article, we will discuss the difference between unit test and integration test.
What is Unit Testing?
It is a software testing type that involves testing a product’s individual components or modules separately. Here, ‘unit’ refers to the product’s single module or component. Every stage of the software development life cycle involves unit testing. Its goal is to identify issues in individual modules or units, fix them, and ensure they work correctly.
To test each component, creating test cases is a must. Test cases used for unit testing are nothing but unit tests.
A unit test is a test case performing certain activities on the source code of a software product’s each module in isolation to ensure that they function as expected.
Unit Testing Example
For example, consider an eCommerce website. Say that you want to test the search feature that provides the result based on the product name you enter. To do so, you need to create test cases for the following scenarios:
- If the product name is empty.
- If the product with the given name is not present.
- If there are multiple products with the same name.
Hence, unit tests ensure that the search feature provides the desired result when users search for any product on the eCommerce website.
Unit tests simply validate the logical implementation of the code. They are structural and do not interact with the user interface. Instead, they only validate each software module for its correctness. Generally, developers are responsible for writing these tests.
Characteristics of Unit Tests
According to Michael Feathers, a test is not a unit test if it:
- Interacts with a database.
- Communicates across the network.
- Touches the file system.
- Can’t run simultaneously with other unit tests.
- Requires special things to do to your environment (such as editing config files) to execute it.
Why are Unit Tests Run in Isolation?
Here are some significant reasons:
- Speed – As per the definition, unit testing evaluates each software module separately. Hence, developers need to create unit tests for each feature of the software product. They need to ensure that these tests do not impact the execution time and performance of the source code. Further, any dependencies between the modules and file systems or databases slow down the text execution speed. Hence, developers run unit tests in isolation.
- Deterministic – Another reason is their deterministic nature. If a unit test fails or passes, it should continue to do so until someone tweaks the faulty code. If a unit test case has dependencies on other test cases, its status may change due to other reasons apart from the code change.
- Scope of Feedback – A unit test case executes on a small piece of code. So, when it fails, it is certain that there is something wrong with that piece of code. This means developers can precisely understand where the errors are located in the source code.
What is Integration Testing?
Integration testing will test the interaction between a software product’s different modules. It takes place after unit testing to ensure that different units or modules work together as expected. The goal is to identify any issues that arise upon the interaction of software modules.
The test cases you create to validate the interaction between different software modules are called integration tests.
Integration Testing Example
For example, you have created two separate modules in an E-commerce app: one is for all the transactions-related methods called the “Transactions Module,” and one for browsing the products called the “Products Module”.
Users who want to purchase a product will add it to the cart. After clicking the “Buy” button in the cart, the Products Module requests the Transactions module to carry out the transaction for this user. This is how these two modules are connected and tested to check their interaction.
Integration tests come into the picture to check the smooth communication between Product and Transaction modules.
Types of Integration Testing
There are different approaches to performing integration testing, as follows:
- Big Bang: Tests different types of modules as a whole.
- Top-Down: Starts testing with the higher-level modules and moves downwards to the lower-level modules to ensure proper communication between them.
- Bottom-Up: Testing begins with lower-level modules and moves upwards to the higher-level modules.
- Sandwich: It combines both top-down and bottom-up approaches, starting with a high-level module and working downwards, and vice versa.
Difference between Unit Testing and Integration Testing
Unit testing and integration testing are different levels of software testing. They have some characteristics in common, as mentioned below:
Unit Testing vs Integration Testing – Similarities
- They are functional testing.
- Their goal is to identify any issues early in the software testing life cycle (STLC) that helps the company to deliver a better product to their clients.
- The same automated tools can perform both types of testing.
Unit Testing vs Integration Testing – A Head-to-Head Comparison
Let us now discuss the major differences between them.
|Test individual units or components for their correctness or functionality.
|Validate the interaction or proper communication between different unit-test modules or units.
|Developers create unit tests.
|Testers or quality assurance (QA) professionals create integration tests.
|They are mostly easy to write.
|They are sometimes hard to write.
|The focus is on individual modules.
|The focus is on a group of modules.
|You can test different units in parallel.
|You need to maintain the proper order of testing.
|They mimic external dependencies like databases, input/output, etc.
|They leverage real dependencies.
|Relatively faster than integration testing.
|Slower than unit testing
|Unit tests provide clear and precise feedback, enabling developers to locate errors in the exact piece of code.
|Integration tests provide comparatively lower precise feedback.
|The maintenance cost is low.
|The maintenance cost is high.
When to Use Which?
The Test Pyramid is a well-known testing framework that you can use to determine which tests to execute and when. It divided tests into 3 layers, as below:
The pyramid shape represents the distribution of tests at each level, with the majority of tests at the lower levels and fewer tests at the higher level.
As you can see, unit tests are the foundation of the testing pyramid. This means unit testing takes place early in the development cycle to ensure each unit performs fine individually. The next are integration tests followed by end-to-end tests.
Unit Test vs Integration Test – White Box, Black Box, or Grey Box Testing?
Let us first briefly understand what white box, black box, and grey box testing are.
- White Box Testing – It is a testing technique that requires developers to have knowledge of an application’s internal structure and implementation details to validate its functionality.
- Black Box Testing – It is completely in contrast to the above one. Here, testers validate an application without knowing its internal structure and implementation details.
- Grey box testing – It is the combination of both white box testing and black box testing. The tester has little knowledge of an application’s internal structure but does not have complete access to its source code.
Unit testing completely depends on the source code implementation. Hence, it is white-box testing. As it requires coding skills, developers generally carry it out. However, it can also be black-box testing, depending on your chosen approach to writing tests. Let us look at both possible scenarios.
Consider your development team follows test-driven development (TDD) using the Inside-out TDD approach (Chicago school, classical school, or bottom-up approach). This approach requires you to create an application by writing low-level unit tests and moving gradually to the high-level tests (acceptance tests). When you follow this approach, unit testing falls under white box testing.
Conversely, consider the opposite. Let us say your team follows the Outside-in TDD approach (London school, mockist school, or top-down approach). This approach requires you to write higher-level tests using test doubles to fill up the dependencies that are yet to be written. You move down gradually to write lower-level tests. Hence, writing high-level tests falls under black-box testing. Those tests generally deal with the API rather than the internal code.
Similarly, integration tests can also be white box or black box testing. Let us understand this with an example.
Consider that you create a React app that uses a GitHub API. You created a component to enter a person’s username and find their repository. Now, you want to test that component using a real GitHub API. In this scenario, it is black box testing, as you don’t know the internals of GitHub API and its working. You depend on its user interface and expect that it does not change.
Integration testing can be white box testing if we write test cases to integrate different source code modules in such a way that they rely on the internal structure.
This was all about the differences between unit testing and integration testing. Both tests are essential to ensure the delivery of high-quality, defect-free software; you cannot skip any of these testing types. Unit tests help uncover the errors associated with each software module. On the other hand, integration tests uncover errors in the interaction of software modules. Hence, each test type has its own purpose in the software development life cycle.
We hope you found this article enlightening!