If you’ve been told that the difference between unit tests and integration tests is that unit tests are isolated, you’ve been misinformed. That is, unit tests are isolated, but that’s not the difference.
You might be asking yourself what the real difference is, but you’d be asking the wrong question. The right question is: why isn’t it isolation?
The answer is really very simple. Unit tests are indeed isolated. But so are integration tests, functional tests, UI automation tests, black box and white box tests, tests that programmers write and tests that QA testers run. I think you see where this is going.
Every test is isolated.
Lets consider unit tests for a moment. A unit test targets a specific function under very specific conditions. To ensure the unit test fails for the right reasons, and only for those reasons, we take extra care to create what we might call a sterile, predictable environment. This is what we usually refer to when we say that unit tests are isolated.
It might seem like the term “isolated integration test” is an oxymoron. How can something with integration also have isolation? Integration tests are more ambiguous and are defined rather loosely, but the comparison works in most cases. Integration tests may not target a specific function, but they do target a specific scenario. They also require very specific conditions. They have to fail for the right reasons, and only for those reasons. And the environment also has to be sterile, predictable. In other words, they also require isolation.
However, the isolation takes a different form. Unit tests isolate a localized function execution environment. The specificity applies to the combination of arguments passed to the target function. And the environment constitutes the state the function requires to execute. We use various tools, such as fakes and mocks, to increase the sterilization.
Integration tests do the same thing, but they test a different target. Instead of testing a function, they test the interaction between a specific set of components. But we have to isolate those components and the environment in which they execute. We might use the same fakes and mocks used for unit tests to create the isolated environment. The environment might be more complex, but a good integration test is still isolated and sterile.
The same is true for other types of tests. Automated UI tests require an isolated environment in which to run as well as sterile, predictable data. We might run automated UI tests on different operating systems and browsers, but we require those environments be sterile and predictable so our bugs can be reproducible.
There are exceptions. That is, there are certain types of tests that are not strictly isolated. For example, exploratory tests are not isolated for the simple reason that they are not predictable. But that’s actually the whole point. They help us figure out how to isolate the conditions and the environment for whatever test we might want to write.
So let’s sum it up. When we write a test, we require that test to be isolated, whether it’s a unit test, an integration test, or any other type of test. The difference between them all is not that one is isolated and another is not, but the specifics and the scope of the isolation.