Menu

Project Nagual

This is a short post to announce a project that I’ve been working on for a while now. It’s an HTTP simulator called Nagual, that can be used to fake responses from 3rd party services outside of your control. We use it to simulate services that we integrate with, mostly the biggest social networks - Facebook, Twitter, LinkedIn, Youtube, Instagram, Google+. By having such simulator, our automated tests are faster, reliable and encapsulated. And the execution time is down from 3 hours to less than 3 minutes.

Which services you should simulate? As a general rule, if a service is under your control, you should not simulate it, instead run its instance (in a container). As an example, currently our application fits in 17 containers that all can run on a laptop. Sometimes this is not possible - in case of legacy mainframes, then even though you control the service you should simulate it as you can have only once instance of it.

When creating Nagual we had some specific features in mind that we could not find in any other public tool (paid or free):

Transparent: No code changes should be required to run this tool. Developers should not even be aware that it exists. The tool should be able to distinguish between legitimate traffic that should be forwarded to the real 3rd party service and traffic that should be simulated.

Fake SSL: The tool should be able to create fake SSL certificates on the fly in order to impersonate legitimate services such as graph.facebook.com and api.twitter.com. Most of the time, these addresses are hard coded in the 3rd party libraries and there is no config option to change them to a server that we desire.

Dynamic Responses: The tool should be able to generate the response on the fly. It should have access to the request (read data if necessary) and programmatically construct a response.

Return Binary Data: Sometimes, we want to simulate downloading a large picture, or video. For this purpose, the tool should be able to return binary data.

Regex URL match: Each of our tests generates all the data that it need before the start of the test. No data is shared between the tests. This makes the tests independent of each other and allows for parallel runs. In the case of a Facebook test, this means that the test should create a random, used-only-for-this-test-case Facebook page. Most of the API endpoints of the social networks are similar, with the exception of an id in the URL. Since the responses are similar, the tool should be able to regex match URLs to reuse the same function to generate responses.

Local Storage: Most of the social networks APIs are complex and to achieve a single action, you need to issue multiple requests. The state and data between the requests should be kept locally by the tool, for usage in any subsequent requests.

Nagual is not record and replay tool (due to our application specific we can not use such tool), as we don't believe such tools are viable in the long run. They create more coupling that you need, and this comes to bite you in the future.

This image is a comparison from March 2016, when we started developing Nagual.

Nagual has one more usage — as monitoring tool. Since it essentially acts as man-in-the-middle proxy, it decrypts all the SSL traffic. Normally, this traffic is seen only by the client and the server. This feature allows you to monitor and log unusual activity on your 3rd party services. We’ve build StatsD support in Nagual. Here is how the 4xx rate of errors looks like when we compare all the social networks

Nagual is not perfect for every HTTP simulation use case, we wrote it to scratch our own need. We tried to make it as robust as possible but it if does not suite you, there may be better alternatives. Also we tried to make Nagual as small as possible, the core is only 700 lines long. Feel free to use it as an example to roll your own tool.

I’ve presented Nagual to Agile Testing Days 2016, here is the link to the presentation. Unfortunately there is no video recording.

If you need more information, check the source code and the documentation on GitHub, and let me know if you have any questions.