Monday, 2 June 2014

Representational State Transfer (REST) API Load Testing

Load testing of a REST API, using HP LoadRunner’s web_custom_request

     In recent years, Representational State Transfer (REST) has become a dominant model for software
architecture, especially for Web-based applications. Today, most large websites and Web applications
on the Internet have REST APIs. Some examples of websites using REST APIs include Twitter, Google,
Flickr and so on.

     The great thing about a REST API is that it is usually well-defined and therefore allows clear separation
between the client logic and the server logic. This property in itself is very beneficial for both functional
and load testing of the application server. In the following article we will demonstrate an easy way to test
your application’s REST API using HP LoadRunner’sweb_custom_request method.

REST API Basics

Before we dive into load testing, let’s look at the basic terminology of a REST API. A REST API call
consists of three major components:

The Uniform Resource Identifier (URI) – This is a string which consists of three parts. The first part
contains the host (and optionally, the port) of the API call (e.g. http://www.hp.com). The second part
contains the path which identifies the call functionality. This path can include some parameter values
although they are distinguishable from the constants only by semantics (e.g. /users/megwhitman/type
/ceo, where “megwhitman” and “ceo” are parameters while “users” and “type” are constants). The third
part is the QueryString which is a list of key-value pairs (e.g. user= megwhitman & type=ceo). The pairs
are separated by the “&” sign and the entire QueryString is separated from the path by the “?” sign. A full
URI may look something like this:

http://www.shopping.hp.com/en_US/home-office/-/products/Tablets/Tablets?SearchParameter
=ElitePad


         The verb – The verb can be any word describing the operation you want to perform on the URI.
In HTTP, the five most commonly used verbs are: GET, POST, PUT, DELETE, and PATCH.
Note that the operation for each verb is determined by the server although there are some common
conventions in this area.

The payload (data) – This is the data sent to the server with the request.

For example, if we want to save a text file to the server, we can send the content of the text file as the
payload.

Test Case

     The example application under test is a todoMVC application which manages a ‘todo’ list. This
application has a REST API, as follows:

/todos, GET, No Payload – Retrieves all the todos currently in the list
/todos, POST, { isFinished :, todoText: } – Creates a new todo on the server with the text provided in
the payload by theparameter.
/todos/, PUT, {id:, todoText: , isFinished:< isFinished>} – Updates the todo with id with the text and
finished state < isFinished>

Note that all the data passed to and received from the server is in the JavaScript Object Notation (JSON)
format
 which is gradually becoming the standard format for data transfer.

HP LoadRunner allows us to easily simulate HTTP calls through the web_custom_request function.
We want to simulate a business process as follows:

1) Get the existing todos from the server

2) Add two new todos

3) Update the last todo added with a new text

Step 1

We use recording to ‘learn’ this step. In VuGen we create a new Web - HTTP/HTML script and record
a browser opening the todoMVC application. When the application starts, it gets all the todos currently
stored on the server through the GET API call. We can easily find the correct step in the recorded script
by looking at the URL argument. In this case the argument is - "URL=http://localhost:3000/todos"
(since the application is running locally on port 3000 on my machine). The relevant step is:

web_custom_request("todos",
"URL=http://localhost:3000/todos",
"Method=GET",
"Resource=1",
"RecContentType=application/json",
"Referer=http://localhost:3000/",
"Snapshot=t66.inf",
LAST);

The “Method” argument is the REST verb (GET in this case), and the “Snapshot” argument links to the
correct snapshot file on the disk. The snapshot of this step can be viewed in the Snapshot Viewer:






We can see that the response from the server is a list of all the todos presented by our application in JSON
format.

Step 2

Adding a new todo is very simple. We create our own web_custom_request step with the parameters
required by thePOST REST API. The created step looks something like this:

web_custom_request("Add Todo",
"URL=http://localhost:3000/todos",
"Method=POST",
"Resource=0",
"EncType=application/json",
"Mode=HTTP",
"Body={\"isFinished\":false,\"todoText\":\"This is VuGen\"}",
LAST);

A few things to notice here:

1) The “Method” (verb) is POST as required by the REST API.

2) We specified the “EncType” parameter to inform the server that the payload is going to be in JSON
format.

3) We added our payload to the “Body” parameter in JSON format.

Since writing the JSON in the middle of the script may be a bit cumbersome, we can add it as an extra
file to the script. To do this simply right-click the “Extra Files” node in the Solution Explorer and select
“Add Files to Script…”, and choose the data.json file we prepared earlier. On a fresh installation of
LoadRunner you may need to specify the .json extension as a valid extension for extra files. You can
also do this after adding the file to your script. In VuGen, select Tools > Options > Scripting > Script
Management and add the .json extension to the Allowed Extensions list. Once the file is added, the project
looks something like this:

                               
                                        


Now we can add the file as our payload by specifying the BodyFilePath parameter:
web_custom_request("Add Todo from file",
"URL=http://localhost:3000/todos",
"Method=POST",
"Resource=0",
"EncType=application/json",
"Mode=HTTP",
"BodyFilePath=data.json",
LAST);

Step 3

We want to update the last todo with some new values. To do this, we use another web_custom_request
with the PUTverb as specified by the REST API. This is very similar to the step that adds a new todo:

web_custom_request("Update Todo",
"URL=http://localhost:3000/todos/3",
"Method=PUT",
"Resource=0",
"EncType=application/json",
"Mode=HTTP",
"Body={\"id\":3, \"isFinished\":false,\"todoText\":\"Updated the name\"}",
LAST);

This command updates the todo with id = 3 with the string “Updated the name”.

As with the previous step, you can manage the JSON text as a file, rather than writing it directly into
the script.

Conclusion

We’ve seen how easy it is to create a simple load test with a REST API using HP LoadRunner.
The web_custom_requestfunction is versatile enough to cover both simple and complex cases, thus
simplifying REST API testing.

No comments:

Post a Comment