Modern applications rarely work in isolation, most often they are integrated with many third-party services. Therefore, there is an urgent need to test this integration in the framework of integration or functional testing. And then you can step on many of the rakes, which I am going to talk about. For whom this topic is relevant, please under the cat.
What is the actual problem?
')
The first solution that comes to mind is to test directly on a real service. In some cases this may be justified, but often leads to the following problems:
- Tests slow down quite strongly . An external service is usually accessed over a network using public protocols, which is much slower than local integration. External service is usually not as fast and is subject to its own load, during which it can slow down even more. As a result, I have seen in practice a slowdown of the integration test suite from 10 minutes to a couple of hours, and the execution time floated heavily.
- Tests are becoming less stable . As I have already said, external services are subject to loads, sometimes unavailable due to updates, they "fall" when service developers incorrectly update, and network errors are also not excluded. All this greatly affects your test suite and its stability. Tests “fall” unexpectedly, it takes a lot of time to study the problem and the team members start to be incredulous about the tests in general. As a result, the very usefulness of testing may be questioned.
- You simply do not have the opportunity to get some external service responses (errors, specific data, etc.), which may affect the coverage of your code with tests, which means reliability of regression testing with integration tests. After all, it is necessary to cover not only positive, but also negative scenarios.
- A real service does not always have a test interface and you have to use a completely real one. And this is not always free and any errors in your code put the real data on an external service at risk . Thanks to this problem, you can easily delete very important data or block access from a real application. And without saying that a lot of money can be spent on the “unexpected” use of an external service.
The problems described cause you to look for alternative solutions and they exist.
Plugs rule the world of testing!
You can come to the aid of various options for stubs (I did not find a better translation of the term
mock objects ). There are several options for stubs: mock, stub, dummy, spy, fake. Knowing and distinguishing between them is necessary and important, so it’s worthwhile to
read and understand the specifics, but this is not about this. We only need one of the types of stubs that are most suitable for working with external services -
fake implementation .
Fake implementation is a simplified version of this service that works completely predictably, locally, gives full access to data and settings, and also does not require any additional work in each test. Thus, we can transparently replace the real service in the tests for fake implementation and solve all the problems. Sounds easy? Not really!
First, we will need to implement this simplified version of the service, which takes time and the efforts of developers. You are lucky if your external service provides fake implementation for local testing. Then you simply download the library, configure it, launch it and use it for health. Some services allow you to access a special version of the external service for testing, which is not subject to the problems listed in the first part. But such a service unit. Almost always you will have to write a fake implementation yourself.
Secondly, you have to take care that your fake implementation behaves in the same way as a real service. This is one of the most frequent rakes, which are attacked by supporters of the described approach. You make a fake implementation today, and after a week the real service starts to behave differently. Your tests still pass and you live in peace until you push your code onto the live servers. And there you will find an unpleasant surprise!
This problem is very easy to fix, but it will take a little more effort. You need to write another set of tests, now for a real service, the purpose of which will be to control and maintain the reliability of the protocol between your application and the third-party service. This is some
kind of smoke test for an external service that can be run once an hour, day or week depending on the stability of your external service. Then you really control and test integration with an external service and avoid surprises when it changes.
I am not ready for such changes!
The described solution is not for everyone (in principle, like any other). Therefore, I will give some tips with which you can smooth out the problems from the first part of this article.
- Separate tests for those where you need integration into external services, and those where only the internal functionality of your product is important. I will give a couple of simple examples. If you are testing the registration, then you probably are not so important system of displaying advertising, pulling up the latest entries from Twitter, etc. Therefore, external services can and should be disabled. Each application can do this in its own way. For example, in a web application it is very easy to use a monitored proxy, which can block access to one of the external services at any time. Such a simple measure will allow you to greatly speed up your tests.
- Actively use custom caching to retrieve data from external services. Usually with integration or functional testing, you go through the same parts of the application repeatedly, and there is not always a need for updated data. Therefore, you can greatly save on calls to external services by caching the results of the previous call. Thus, you are still testing the acquisition of real data, but much more optimally.
- Be sure to look for open source fake solution for your service. Usually for popular services it exists, since many people come across a similar testing task and not all of them are as lazy as you. For example, there is a great fake-s3 project for working with Amazon S3 service. It implements the same API, allowing you to test integration for free, safely and locally. All you need is the ability to configure access to the service in your application.
- Check with the service provider if it has the ability to localize testing. Perhaps you just do not know about the existence of such solutions or push the provider to create it. For the demand is not hit, as they say.
Someone even this set of measures will significantly improve their testing.
Conclusion
In general, the most important thing is to understand the problems described and to have the desire to solve them. Then you can come up with many alternative solutions and approaches that will work even better than those given in the article for your particular case. And then your tests will again be fast, reliable and even more useful for your team.