As a junior or medium experienced developer you sooner or later reach the point when you don’t ask whether you should have automated tests, but which kind. When you google this question, you will find the two most popular approaches : unit testing and integration testing. You might ask yourself, which of them should I use in my project? Let’s look at the question of what should be used: unit or integration testing.
Let’s start with unit tests. Martin Fowler gave one of the first opinions about the question in his famous Test Pyramid.
The most essential statement in the pyramid is that your fundamental testing should be based on unit tests. Unit tests are an approval layer for the building blocks of your application. If you have classes or modules which follow the single responsibility principle, you should have corresponding unit tests covering them. You’ll find some advice for unit testing below.
When you use unit tests, you should keep in mind that you need to use data sets which are possibly very close to the production samples. That means you need to come up with meaningful data sets or copy them from productive use cases. Don’t be lazy, don’t just use some empty strings or nulls to pass into your unit test methods, unless you want to test exactly the behaviour with these specific values.
Strive for broad coverage by your unit tests. Try to cover all known test scenarios which are expected by the business side for a unit. In the event some dependencies bother your tests, make use of mock frameworks such as Mockito to concentrate on the units (in case of Java - classes) which are tested. Let’s proceed with…
In contrast to unit testing in your system, you should also test the integrity of all these units. It won’t be helpful if you discover a failing unit test and fix it but in the end your application doesn’t start because of a failing dependency injection.
There are few approaches on how to test the integration of the system. The first and naive one is end to end testing - meaning you start the complete system within your test infrastructure and run your test scenarios against that. The problem with this approach is of course the startup times. Ideally, for each test set, you need a fresh version of the application with surrounding systems, e.g. an empty database. That means all surrounding systems ideally should be removed and initialized again after each test case. The restart and cleaning up infrastructure would take time.
Because of this problem, some frameworks provide you with the possibility of test slicing, i.e. you don’t start the whole application in order to test only the reads and writes on the database. For this purpose you will only start the database slice. The same can be done for security, http or messaging layers.
As you can see, both approaches are very important for maintaining the quality of your software. You should definitely use both of them in your main CI/CD pipeline. You could additionally add some other types of tests to separate pipelines. For instance, you can run end to end tests only once a day if they last too long.
PS. You can also consider adding contract testing for better integrity with external systems.
Bellow is a short comparison with pro and con:
Image Credits go to Ralf Kunze from Pixabay