What Is API Testing and Why Should We Be Using It?
Many companies are moving toward a microservices model for their software applications. This means that different sections of their application can have separate datastores and separate commands for interacting with that datastore.
Microservices are appealing to software providers because they allow components of the software to be deployed more quickly; while one area of an application is updated, the other areas of the application can continue to function.
We live in a time when users expect software to be ready to use whenever they want it, and the microservices model ensures that an application will not be down for maintenance when a user wants to use it.
Most microservices are using application programming interfaces (APIs), which are a set of commands for how a service can be used. And most APIs are using Representational State Transfer (REST) requests through Hypertext Transfer Protocol (HTTP) to request and send data.
In spite of this fact, many software testers continue to automate their testing with user interface (UI)-based tests that interact directly with the browser. This is largely due to the success of the Selenium suite of tools for test automation, which runs in a web browser.
Selenium has been available for several years, and most software testers are familiar with its use. But the most familiar tool is not always the most appropriate tool to use in test automation.
While some UI testing will always be needed to verify that elements appear on a page and can be interacted with, API tests are much faster and more reliable than UI-based tests. When testing things like adding and removing records from a database, automated UI tests can be time-consuming and repetitive. API tests allow for rapid record manipulation.
Furthermore, API testing allows the tester to find bugs earlier in the development process, often before the UI has been created. And API testing allows the tester to make requests that might not be allowed through the UI, which is crucial for exposing potential security flaws in an application.
Because changes in software happen at such a rapid pace today, it’s important to have tests that provide fast feedback for developers and testers. API tests can fill this need. We’ll describe the fundamentals of API testing, including how REST requests work and how to set up requests and assertions.
How Does a REST Request Work?
Before diving into API testing, you’ll need to learn a few of the basics. An API is made up of a set of REST requests. These are the requests made to an application server that retrieve, delete, or manipulate data in an application’s database.
A REST request is made up of the following parts:
- An HTTP verb that describes what action should be taken
- A Uniform Resource Locator (URL) that defines the location of the request
- HTTP headers that provide information to the server about the request
- A request body that provides further details for the request (this can sometimes be empty)
Here are the most common HTTP verbs:
- A GET request fetches a record from a database
- A POST request adds a new record to a database
- A PUT request replaces a record with a new one
- A PATCH request replaces part of a record with new information
- A DELETE request removes a record from a database
The URL used in the request clarifies which type of record will be altered by the request. For example, a GET request used in conjunction with the URL https://www.example.com/cars/1 would return record number 1 in a table of cars.
Similarly, a GET request used in conjunction with the URL https://www.example.com/trees/2 would return the second record in a table of trees. The end of the URL specifies an endpoint—a data object used in the API. In these examples, the endpoints would be /cars and /trees.
HTTP headers can provide information to the server such as:
- The Host: the domain and port number of the user making the request
- Authorization: the credentials of the user making the request
- The Content-Type: the format of the information provided in the body of the request
The request body is used when making POST, PUT, or PATCH requests. The body specifies exactly what information should be added to the database. It is usually in JavaScript Object Notation (JSON) or Extensible Markup Language (XML) format.
Here is an example of what a JSON request body might look like for doing a POST request that adds a customer to a database:
{ “firstName”: “John”, “lastName”: “Smith”, “emailAddress”: “jsmith@example.com” }
Understanding the parts of a REST request will help software testers formulate requests for testing purposes. Simply knowing that clicking the “Send” button in a form will send a POST request is not enough; to truly test an API, a tester should know how to create and send a request without relying on the UI.
It’s also important to understand what to expect as a response when a test request is sent; otherwise, the tester will have no way of knowing if the API is functioning correctly.
What Is Included in the Response to a REST Request?
The response to a REST request is the information that the server sends back after it has received and processed the request. It will include HTTP headers that describe the response, a response code that describes the success or failure of the response, and a response body that includes requested or relevant information (this can sometimes be empty).
The HTTP headers in the response provide information to the requesting party such as:
- Access-Control headers: tell the requester what types of requests and headers will be allowed
- The Content-Type: the format of the information returned in the response
- The Server: the name of the server that responded to the request
Response codes are three-digit codes used to describe the result of the REST request. The most common response codes come in one of these three categories:
- 200-level responses indicate that the request was received, understood, and processed
- 400-level responses indicate that the request was received, but that there was an error from the client
- 500-level responses indicate that there was some sort of server error
The response body will vary by what type of request was made and whether there was an error in the request.
A successful GET request will return a body that has the information requested. A successful POST request might return a body that echoes the body sent with the POST, or it might return an empty body with a 200-level response code. A request that returns an error may have an error message in the body of the response.
How Can We Test APIs?
Now that you’ve learned the mechanics of how a REST request and response work, it’s time to learn how to test them. The first step in testing an API is to determine what sort of REST requests can be made by the API and what the limitations are for each request. This can be done by looking at the documentation.
Some developers may choose to document the API by using Swagger, which is an open-source framework that clearly describes an API’s behavior. There are other documentation tools available as well.
In order to test an API completely, it’s important to understand what the limitations are for each REST request in the API. Finding, testing, and verifying those limits is crucial to making sure that the API will behave in a way that users expect, and that the API cannot be exploited by malicious users to get information they should not have access to.
Here are some questions to ask the API developer when collecting information about an API:
- What endpoints are available?
- What HTTP verbs can I use with those endpoints?
- Are any of the verbs limited by authorization?
- Which fields are required in the requests?
- What are the validation limits on the fields?
- What response codes should I expect for a successful request?
- What response codes should I expect for an unsuccessful request?
- What sort of error messages will be returned in the body of an unsuccessful request?
The next step is to set up each of these requests in an API test tool.
A variety of tools can be used for this purpose. It is also possible to write API tests directly into code, but the advantage of API testing tools is that they are easy to use and provide a way to visualize the response.
The easiest API testing tool to use is Postman. It has a 100 percent free version that can be downloaded quickly, and there are also paid versions for teams. Runscope and SoapUI are two other popular tools. For more suggestions on API testing tools, check out Simple Programmer’s Ultimate Automation Testing Guide.
Once you have chosen an API testing tool, the first requests to set up are the “happy path” requests. These are the requests that the API developer would expect that users would make in the normal course of using the application.
When setting up a “happy path”-style request, it is important to include assertions. One assertion should be that the correct response code is returned (often a 200 response).
If the response includes a body, there should be an assertion on that as well. For example, if a GET request is being tested, there should be an assertion that the body of the response contains the data that was expected with that record.
Once all of the “happy path” tests have been created, negative tests can be added. Negative tests are those that make sure that any kind of error is handled correctly. It’s important that an application doesn’t crash when a user accidentally imports invalid data, and it’s important that a malicious user is prohibited from entering harmful scripts into the database. Here are some examples of negative tests:
- Sending a request with the wrong HTTP verb
- Sending a request with the wrong endpoint
- Sending a request with the wrong headers
- Sending a request with missing headers
- Sending a request without the proper authorization
- Requesting data for a record that does not exist
- Sending a request with a body that has missing required fields
- Sending a request with a body that has invalid field values
This Sounds Great, But Can You Walk Me Through an Example?
Yes! The developers of Swagger UI have created an API to practice on, called the Swagger Petstore. This is the only public practice API I know of that provides a clear visualization of how each API request works, and also provides a way to try out requests directly in the documentation. We can create a request that points to this API in Postman, add some assertions, and run it from the command line with Newman. Newman is a command-line run tool created by Postman that can be installed through the node package manager (npm).
Step 1:
- Navigate to http://petstore.swagger.io and click on the request “GET /pet/{petId}” to open it
- Click the “Try it out” button
- Put the number 1 in the field marked “ID of pet to return”
- Click the “Execute” button
- Scroll down to the Response body and verify that a record for a pet has been returned (if a record was not returned, try the request again with a different ID in the “ID of pet to return” field)
Step 2:
- Download Postman by going to https://www.getpostman.com and clicking the “Download the App” button
Step 3:
- Launch Postman
- In the top middle of the screen, verify that you see the word “GET” in the HTTP verb dropdown
- In the space beside the “GET,” enter this URL: http://petstore.swagger.io/v2/pet/1 (If you are using a different ID than 1, replace the 1 with the ID you chose.)
- Click the “Send” button, and verify that you receive a response code of 200 OK, and that the response body contains the record for the pet
Step 4:
- Click on the “Tests” tab found underneath the URL of the Postman request
- On the right of the screen, scroll through the selection of code snippets until you find the one titled “Status code: Code is 200,” and click on this title
- Note that this assertion has been added to the test window. The code asserts that 200 is the response code you get when you send the request.
Step 5:
- Scroll through the selection of code snippets until you find the one titled “Response Body: JSON value check,” and click on this title
- Note that this assertion has been added to the test window
- Change the string “Your test name” to “Correct pet ID is returned”; this will be the name of the test
- Change the value in parentheses after the word “expect” from “jsonData.value” to “jsonData.id”; the test will be checking on the value of the pet ID
- Change the value in parentheses after the word “eql” from “100” to “1” (or whatever ID you chose to use in the GET request)
- Click the “Send” button again, and click on the “Test Results” tab
- Verify that you see the two tests you created with the word “Pass” next to them
Step 6:
- On the left side of the screen, click the “Collection” tab
- Click the icon with the folder and the plus button to create a request collection
- In the popup window, give the collection the name “Pet Store” and click the “Create” button
- On the right side of the screen, click the “Save” button
- In the popup window, give the request the name “Get Pet”
- Select the Pet Store collection
- Click the “Save to Pet Store” button
Step 7:
- Hover over the collection name “Pet Store”
- Click on the three dots that appear beside the collection name, and choose “Export”
- Choose the v.2.1 collection option and click the “Export” button
- Choose a location to save the collection to, such as your Desktop
- Remove the space between the word “Pet” and the word “Store” in the file name
- Click the “Save” button
- Your collection will be saved as a JSON file called PetStore.postman_collection.json”
Step 8:
- If you do not already have Node.js installed on your machine, install it using the instructions found at https://nodejs.org/en/download
- Open a command window, type “npm install -g newman” and click the Return key. This will install Newman onto your machine. If you are new to using the command line, see this article for some of the common commands
- Using the command window, navigate to the location where you saved the JSON file (for example, you might type “cd Desktop” to change to the Desktop folder)
- Type this command into the command window: “newman run PetStore.postman_collection.json”
- You should see your tests run and pass in the command window!
How Can We Automate API Testing?
Once a complete suite of positive and negative tests has been created, automation can be set up. The Newman command to run the tests can be integrated into a continuous integration (CI) project. Similarly, Runscope and SoapUI also provide command-line functionality for integration with CI tools.
Next Steps
The above tutorial is just a simple example of what is possible in API testing. To go further, you can try out more of the requests at the Swagger Petstore and create tests for them in Postman.
If your company is developing APIs, you can take a look at the APIs to find out what kinds of automated API tests you could set up for your software.
Examine your automated UI tests to see which ones might be better covered by API testing. For example, if you have a UI test that fills out a customer form and adds a new record to the database, you could instead have an API test that uses a POST request to add the record. API tests are best for testing the creation and manipulation of data, while UI tests are best for checking the on-screen availability and usability of buttons and links.
Moving the bulk of your automated tests to API testing will allow your test suite to run much faster and more reliably. You will be able to quickly uncover flaws in the manipulation of the data store, and expose any potential security holes before they can be exploited. Happy testing!
Published on Java Code Geeks with permission by Kristin Jackvony, partner at our JCG program. See the original article here: What Is API Testing and Why Should We Be Using It? Opinions expressed by Java Code Geeks contributors are their own. |