Sitemap

Understanding Integration Tests: Scoping Strategies, and Incremental Testing Techniques

Integration Test, Incremental Integration Test, Bottom-Up, and Top-Down

6 min readMar 19, 2024

--

Topics Covered:

  • The Idea Behind Integration Tests
  • What Exactly Are Integration Tests
  • Integration Tests vs. Unit Tests
  • Define the Scope (Broad, narrow)
  • A Bigger System to Test
  • Incremental Integration Test
  • Bottom-Up
  • Top-Down

The Idea Behind Integration Tests

Integration tests ensure that different parts of a software system work well together. It’s like making sure all players in a sports team can play together effectively. In software, each team develops a module, and integration tests ensure these modules can be combined into a larger system seamlessly.

Press enter or click to view image in full size

What Exactly Are Integration Tests

In software development, features are often built upon different layers or modules. These layers can include the user interface, business logic, and network connectivity. Each layer serves a specific purpose, such as managing the UI or handling data interactions. It’s common for apps to have multiple layers, sometimes as many as five, six, or seven. The best practice is to test each layer individually and then test how they function together as a complete system.

Press enter or click to view image in full size

Notice that an integration test can be between two modules or more or the whole system.

Integration Tests vs. Unit Tests

The first confusion developers have with integration tests is with the creation of such a test. If you recall, we have only two ways to create a test in XCTest — UI and Unit Tests. Integration Tests fall under Unit Tests in this case.

Another confusion is what exactly is considered to be an integration. For instance, if you test a function that relies on another logic function, is that an integration? And let’s say that this function uses some helper class in your project, is that integration as well? After all, two classes talk to each other — sounds like integration to me.

Well, not every communication between classes and functions is considered an “integration” in our case.

In iOS Integration Tests, it is common to test integration between layers of our architecture, which means testing the layers according to the data flow and not just the use of external functions or classes.

Also, in Unit Tests, we have heavy use of test doubles. It’s not that integration tests don’t include test doubles — they are, but much less and mostly on the edges (we’ll cover that later).

Define the Scope

When conducting integration tests, it’s crucial to define the scope of testing. Some layers, like the Network Layer responsible for server communication, and the UI layer, can be challenging to test due to dependencies like network connections or loading classes from XIB files. While testing the entire system from the UI layer to the server is ideal for comprehensive coverage, it can be difficult to implement, maintain, and slower to run. Therefore, it’s essential to balance thoroughness with practicality when defining the testing scope.

Take a look at the feature architecture

Press enter or click to view image in full size

Integration Tests scope: displays a classic screen architecture — from the UI Layer down to the iOS SDK frameworks. You can see we can do extensive testing, meaning do some action on the UI Layer and examine the effect on the other edge (e.g., Core Data), or do a narrow test — test some of the layers and use test doubles for the rest of the system.

The ratio between effectiveness and cost

Press enter or click to view image in full size

As you can see, Narrow Integration Tests are much more useful than Broad Integration Tests, just like the difference between Unit Tests and Integration Tests in general.

Too many integration tests can make you spend much time maintaining them from breaking up, more time than Unit Tests. On the other hand, testing the critical flows gives you more confidence in your app and your code.

A Bigger System to Test

Identifying the fault point may not seem like a big issue when dealing with a three-layer architecture. However, there are features and architectures with five to six layers that are more difficult to integrate and debug.

Press enter or click to view image in full size

How do we write an efficient integration test for such an architecture in a way that can help us track issues? One approach can be an incremental integration test.

Incremental Integration Test

We know that testing integration between several layers can be an issue, but testing integration between two layers is much more straightforward. In Incremental testing, we take our architecture and start with the first two layers. At each step, we add one more layer to our test and recheck it until we add all of our layers.

Press enter or click to view image in full size

In this way, we are re-testing our integration in each step, which makes it easier for us to locate the problem.

Well, there are mainly two ways of implementing an Incremental Integration Test — Bottom-Up and Top-Down.

Bottom-Up

If the UI layer is considered to be the Top layer of our architecture, the core services layer is the “Bottom” one. When talking about “top” and “bottom,” we usually refer to layers that are closer to the user level as “Top” and layers that are closer to the system level as Bottom.

Press enter or click to view image in full size

In BUA (Bottom-Up Approach), we test the integration starting with the Core Services layer and add one more layer on top of it until we fully cover the system.

Press enter or click to view image in full size

BUA test suite for the calendar feature

The preceding diagram describes the list of tests we write to come up with incremental testing to our feature. As you can see, we are adding one test in each step. Just like standard unit tests, it is recommended that you test each step in a test method of its own to separate your tests from each other.

The Bottom-Up approach is easy to implement and reduces the use of test doubles. However, using the Bottom-Up approach is not possible, and you have to go with Top-Down Incremental testing.

Top-Down

There are cases when the bottom layers are not ready yet. In fact, this is the usual situation when starting with the development of a new feature. We start by defining the interfaces between all layers and then continue to develop it top to bottom.

Press enter or click to view image in full size

As we make progress in our development, we want to make sure our components are integrated correctly. Since our bottom layers are not ready yet, we can create a stub to replace them and, by that, create incremental tests on the go. This approach is called “Top-Down,” and it is usually the approach we take during development when there are components that are not ready yet.

Reference:

  • iOS unit test by example
  • Pro iOS Testing

If you have any questions or comments on this tutorial, do not hesitate to contact me: Linkedin, Twitter, Email: alsofiahmad@yahoo.com.

Thanks for reading!😀

--

--