As anyone will tell you, APIs are the glue that holds together all modern web and mobile applications. Without APIs, frontend clients wouldn’t be able to communicate with backends and no services could function. The history of APIs is relatively short, really only going back to the days just after the .com bubble. Early pioneers like Salesforce were looking to create a way to allow web applications to be developed in a more dynamic and responsive manner. The approach they pioneered has gone on to redefine how all applications work and nowadays it’s almost impossible to imagine developing an application without an API.
For something so vital, the history of API testing is a mixed picture. In this blog, we will explore the history of APIs, look at some of the approaches to testing that have been used in the past, introduce the current best practices and finally look at how cutting-edge techniques like machine learning can improve the process.
History of APIs
As mentioned above, the history of modern APIs really began in 2000 with the birth of Salesforce. Prior to that, many large organizations had bodged together systems that allowed data to be shared between their different branches. For instance, shops often had shared systems for stock taking, etc. However, these systems generally relied on being on a private network of some form. By contrast, modern APIs allow data and commands to be shared across the Internet.
APIs generally follow one of two approaches, RESTful or SOAP. RESTful (standing for REpresentational State Transfer) is far and away the most common nowadays, but the early APIs tended to use the SOAP Web Services model. In both cases, the job of the API is to provide a standard format for exchanging data between frontend and backend systems using normal HTTP messages like GET and PUT. The content of the message is usually in XML (for SOAP) or JSON (for RESTful APIs), though some developers may choose to use XML with RESTful APIs.
In the early days, APIs were purely used for specific applications and services within a company. But quickly they began to offer a way for companies to offer their services to other companies. For instance, a shopping website will use external 3rd party APIs to handle payments and shipping/tracking.
From 3rd party APIs, it was but a short step to creating “API mashups”, where APIs are repurposed to offer new functionalities that go beyond their core use case. Possibly the best example of this is the multiple ways in which the Google Maps API has been used to provide embedded geospatial information in apps and websites. Nowadays you can find Google maps being used for everything from showing interactive routes for marathons to showing details of the archaeology and history of the Berlin Wall.
APIs need to be designed to be robust, secure and extensible. To achieve this, the API developer ideally needs to generate a very precise API specification. This will determine exactly what API calls are needed, what each call will return, what data it will encapsulate (including the format of that data) and give details of any error messages. Of course, as we all know, many developers take a more organic approach than this, adding API calls as and when they are needed. In either case though, without suitable API calls, it will be impossible to build a modern web or mobile app.
Mock API Servers
Over the years, people have become much savvier at designing (and testing) APIs. One of the biggest advances has been the creation of Mock API servers. Essentially they take an API specification, usually written in some standard format, and use this to generate a server that is able to correctly generate and return mock API calls. This allows APIs to be developed in isolation from the frontend and backend code. One of the best-known systems for this is Swagger, but there are other alternatives such as the API Blueprint project.
Swagger, in particular, pushes a new paradigm for the development of web applications. They suggest that you start by fully defining your API specification, then create the system round that. The specification serves both as the basis for the system functionality and as the basis for the eventual documentation that will allow developers to build and extend the system. The specification also provides the required information for testing the API.
In the early days, API testing was extremely limited. Generally, it either took the form of unit testing, where the API developer tests each command in isolation and checks that the expected result is being returned, or it forms an implicit part of the integration testing, where end-to-end tests require the API to function in order to complete successfully. But testing APIs is about more than simply testing their functionality. APIs also have to be secure, robust in the face of unexpected calls and should be reliable even under heavy load.
Nowadays, API testing tries to take account of all these things. Broadly, modern API testing can be split into the following categories:
Unit and Functional testing. This seeks to test each API call or call sequence in isolation. It’s about ensuring that the API call is handled properly, that it returns sane results and can handle errors smoothly.
End-to-end/UI testing. This type of testing checks that the system as a whole is making the correct API calls and is receiving the correct responses in order to allow it to function properly. Often this is implicit within the main system testing, but it may be done more specifically, especially for instance when you are changing an API.
Load testing. This is about ensuring the API servers/services can handle the load that is expected in the system. It should also check that they fail gracefully rather than just falling over in a mess.
Security testing. Here the aim is to test things like API key generation, key expiry and other security-related aspects of APIs. Because API calls are carried over the Internet (albeit usually in an HTTPS stream), they pose a real potential security threat.
Integration testing. As we have already mentioned, many web applications rely on several external APIs to function. It is vital to test these integrations properly, including testing what happens when you send or receive unexpected data.
API testing as an alternative to system testing
Modern web applications are often highly complex, dynamic and need to be tested under high loads. As a result, there has been a trend for people to use API-based methods for test automation. Here, a relatively dumb process generates a large volume of API calls and checks that the responses are as expected. APIs can even be used to construct quite sophisticated test suites that test all your backend systems properly. However, this approach is unable to test GUI/frontend aspects of the application.
Looking to the future
There has been a growing trend to apply Artificial Intelligence (AI) to all forms of testing. Machine Learning, in particular, offers some exciting prospects for improving how we test web and mobile apps, generating tests from observing user interactions and creating self-healing tests. For API testing, Natural Language Processing, combined with Deep Learning, offers some intriguing possibilities, such as creating a system that can use the API specification in combination with things like user stories to define both the API and the frontend tests.
Here at Functionize, we are already exploring the use of NLP to define automated application tests based on your test plans. Going from this to generating API tests from API specifications is a simple step, especially given the formal nature of most API specifications.
APIs are crucial for any modern web or mobile application, yet as we have seen, often they have been overlooked when it comes to testing. Nowadays, people are waking up to the need to test APIs properly, both to ensure their app works correctly and as a vital part of ensuring the security and scalability of their systems. In the near future, machine learning offers the promise of intelligent API testing, where tests are automatically created from the API specifications, freeing up human testers to concentrate on exploratory and security testing.