At the time of writing this, the top hit from Google for “unit testing” produced this:
“Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation. Unit testing can be done manually but is often automated.” – http://searchsoftwarequality.techtarget.com/definition/unit-testing
Likewise, the top hit for “integration testing” produced this:
“Integration testing (sometimes called integration and testing, abbreviated I&T) is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing.” – Wikipedia
Now these are reasonable descriptions of these two methods of testing and very likely what the common understanding would be. However, they don’t really tell us what a “unit” is or what “software modules” are. In general, we might think of a “unit” as a single class or even a method within a class. Similarly, we might refer to a “software module” as a group of classes, or maybe even an assembly.
In order to “independently” scrutinize a “unit” for proper operation we must isolate that unit of work from everything else. Conversely, when combining modules to be tested as a group it stands to reason that they could be just the combination of two (or more) units of work.
This viewpoint has lead me to the following definition of both Unit and Integration Testing.
“Unit Testing is testing a single unit of work (think operation) in isolation with no other dependencies”.
This means that the code being scrutinized for proper operation can only be a single method within a single class that does not interact with any other non-mocked object or resource. It should not interact with the file system, memory cache, database, or anything else. It may leverage other internal (or private) methods within the same class but not another class or component. This single operation will likely require several tests to validate all possible execution paths and input/output combinations.
“Integration Testing is testing any software module, component, or unit of work with its dependencies”.
This really simplifies things for us, because now we can say the difference between the two is:
“Unit Testing is testing a single unit of work without any dependencies and Integration Testing is pretty much everything else.”
With this understanding we can say anytime we are testing a unit of work that calls another class, or accesses a file, or makes a call to a database, or pulls values out of a cache it is really an Integration Test. Unit Testing now becomes a specialized subset of our testing suite which has clear and clean rules of separation from other types of tests.
Using mocks can be a necessary strategy to ensure we can isolate the code to be Unit Tested. Mocks enable us to control the flow of execution for each test ensuring a much higher (and easier to achieve) code coverage. Integration Tests therefore cover a wide range of tests including but not limited to the following:
- Component (or class) Integration
- Use case Integration
- Feature integration
- UI Integration
- System Testing