We’ve already discussed TDD and the importance of testing. But how much testing do you need to do? And what should you be testing? Let’s explore four types of testing: unit tests, integrations tests, regression tests and acceptance tests.
- Unit – You test each individual piece of code. Think each class or method.
- Integration – You test the integrations of many units together. You make sure your code works when put together, including dependencies, databases and libraries.
- Regression – After integrating (and maybe fixing) you should run your unit tests again. This is regression testing to ensure that further changes have not broken any units that were already tested. You can run your unit tests again and again for regression testing.
- Acceptance – You should test that the program works the way a user/customer expects the application to work. Acceptance tests ensure that the functionality meets business requirements.
A unit test is a test written by a programmer to verify that a relatively small piece of code is doing what it is intended to do. They are narrow in scope, they should be easy to write and execute, and their effectiveness depends on what the programmer considers to be useful. The tests are intended for the use of the programmer, they are not directly useful to anybody else, though, if they do their job, testers and users downstream should benefit from seeing fewer bugs.
Unit tests shouldn’t have dependencies on outside systems. They test internal consistency as opposed to proving that they play nicely with some outside system.
I’ve been using Rspec to perform unit tests with my Ruby applications. I typically test each method in each class to ensure functionality at a very low level. You decide what the unit is by looking for the smallest testable part.
An integration test is done to demonstrate that different pieces of the system work together. Integration tests cover whole applications, and they require much more effort to put together. They usually require resources like database instances and hardware to be allocated for them. The integration tests do a more convincing job of demonstrating the system works (especially to non-programmers) than a set of unit tests can, at least to the extent the integration test environment resembles production.
“Integration test” gets used for a wide variety of things, from full-on system tests against an environment made to resemble production to any test that uses a resource (like a database or queue) that isn’t mocked out.
Ultimately you should write integration tests to make sure your code plays nicely with other code you are making use of. There is whole spectrum from testing integration between two classes to testing integration with the production environment.
Regression tests are performed whenever anything has been changed in the system in order to check that no new bugs have been introduced.
This means you re-run your unit and intergration tests after all patches, upgrades, and bug fixes. Regression testing can be seen as a special case of combined unit test and integration test.
Acceptance tests make sure a feature or use case is correctly implemented. It is similar to an integration test, but with a focus on the use case rather than on the components involved.
There are many ways to perform acceptance tests. The customer or user can manually test the application to make sure it meets each of the business requirements. Or you can use automated testing tools, such as Cucumber and Selenium.
Acceptance tests act as the final verification of the required business functionality and proper functioning of the system, emulating real-world usage conditions on behalf of the paying client or a large customer.
Read more about the differences between types testing from developers who are much more experienced than me: