As Microservices and APIs become more prevalent in modern software development, testing and validating these APIs is increasingly important to ensure the quality of your software.
Testing APIs and microservices offer a host of benefits. First, they allow you to easily test end-to-end behavior, without having to invest in writing and maintaining UI based testing, by mimicking the API calls clients would generate. This allows for stable and easy-to-write tests and can help identify exactly where in your system problems originate. API tests can also be easily run as monitors, allowing you to easily identify outages and performance degradations before your users do! However, unlike more common classes of tests like end-to-end testing and unit testing, API testing is a newer field for many engineering teams. To that end, this article will help you get started with testing your APIs.
1. Learn Why Organizations Are Prioritizing API Testing
The importance of testing your APIs cannot be overstated and oftentimes, it yields value much more quickly than other forms of testing. This is due to a few factors that make API testing compelling:
Mimicking User Flows — functional API tests can follow common user flows and perform the API calls those flows will yield. These tests can instantly validate full user flows in your system and make sure that they are functionally supported, very much like end-to-end UI tests.
Test Stability — UI tests are commonly used to test full system flows, but the problem is that UIs change very frequently, often breaking UI based tests and making test maintenance a growing concern. On the contrary, APIs are built to be a stable interface, making tests based on APIs a lot more stable and lowering the cost of maintaining tests.
Test Cost — API-based tests meet a happy medium of testing big parts of functionality while being relatively quick to build. Unit tests are simple to build, but you need to write a lot of them to get good coverage of system behavior. A few UI tests can quickly cover a large system, but building them is very time-consuming.
Pin-point problems — often when software problems arise, the hardest part is to know where they originate. With API tests, you can pretty quickly dissect the system and understand if problems lay behind the API (in the backend) or in the software UI.
2.Understand the API Behavior
The first step for writing any API tests is to develop an understanding of what the API does and how it works. There are three levels of understanding of what the API does:
API Scope — basically, what functionality does this API offer? Often this takes the form of just understanding what endpoints the API offers (for RESTful APIs) or what queries and mutations the API exposes (for GraphQL APIs).
Endpoint Functionality - once you scope all the available endpoints in the API, now it’s time to understand what they all do and how they work. On the surface, this is as easy as just knowing what the endpoint is expected to do, but ideally, in this step, you should start developing an intimate understanding of these endpoints — what parameters they expect? What is the range of possible values? What are the edge cases and what happens when they occur? The best way to do this is to just make requests to each endpoint trying different scenarios and inputs until you feel like you have a solid grasp of how it works.
User Flows — it’s not enough to understand what every part of the API does; it’s also imperative to understand how APIs come together in an application. Take a deep look at the application consuming these APIs and make sure you understand how that app is used, and how that usage leverages the API.
The more time you spend really understanding the API, the better tests you’ll be able to write!
3.Create Assertions on API Response
When you make API requests in your test flows, don’t be satisfied with just a successful response. Think of what the API is expected to return and what format that data could be in, and spend time ensuring that the data return does fulfill the API contract. Broken response schemas or missing data can wreak havoc on the end application — this is a good opportunity to catch these bugs before they happen!
4.Create Functional Flows with the API
Calling every endpoint in the API and making sure it does what it is meant to do is nice and dandy, but the bigger question is — does the API functionally operate as it should? The way to test this is to create complete functional flows with tests — add data, check it is there with another call, modify it, check the modifications, and so forth. You should use your familiarity with the end application to mimic the API calls that will be made during normal usage of the app.
Example: In an eCommerce API for instance, complete flows will include user registration, product search, adding products to basket, and checking out.
5.Make Tests Encapsulated
Good tests are completely encapsulated — meaning they do not rely on pre-existing data to run. Every test should start by making the API calls necessary for subsequent steps. Example: If you need a user, the first step should be creating it, and the last step should be making an API call to remove it. Tests that rely on pre-existing data can fail because of changes in the environment / missing data and create false alarms.
6.Test Success and Failure Scenarios
When constructing tests, think of edge cases and scenarios where the API should fail/block a request. Example: Trying to access a resource you are not authorized to view, trying to get an item that does not exist, or passing a misformatted parameter to the API endpoint. These will help venture beyond ensuring basic application sanity and make sure no issues or potential security risks are lurking below the surface.
7.Integrate API Testing Into the CI/CD Workflow
As you are making changes to your software and deploying new code versions, API tests can help ensure that your application won’t break. Seek out an API testing tool that can be triggered by your CI/CD tool, and make sure those run tests every time you push new code.
Good API testing can help ensure that your APIs are functional between deployments and that the schema they return has not inadvertently changed — risking other applications that depend on them.
8.Monitor Live APIs
Beyond being useful for validating your code, API tests offer great value in monitoring your production system. Run the test against your production environment on a set schedule to validate that it is up and running all the time, and functioning as needed. Assuming you followed tip #5 (making your API tests encapsulated) you should be easily able to run them in multiple environments. What’s more, a good API testing platform will be able to measure and analyze the API call latency over time, and not only alert you if your system breaks, but also if the performance degrades dramatically.
9.Define Alerts on API Tests
Tests are not very useful unless they give you timely, actionable feedback on the status of your system. Whether they run periodically to monitor your production environments or in your CI/CD pipeline on every new code version, you want to know immediately when a test fails so you can remedy the situation. Good API testing platforms will allow you to define SMS, email, and other channels of alerting when a test fails.
10.Integrate Testing into your Development Cycle
Developing tests should not be a discrete task that happens once, but part of every advancement in the codebase. Whenever you extend the API, add additional functionality, or support new user flows, make sure to test them as part of the development process, and enjoy the peace of mind of knowing that your APIs are fully covered and validated continuously.
Over time, this approach will allow you to quickly cover all your major functionality with tests.