Postman - API testing Made Easy

Akila Rajkanth
Akila Rajkanth
Contents

Postman is a great platform where one can design, build and test APIs. Postman’s main features include API Testing, automated testing, building APIs with mock servers, publishing machine readable API documentation and Monitoring API health. At Trimble Maps, we predominantly use Postman in automated testing to aid us in the DevOps process. Using Postman collections allows us to continuously deliver software with a high level of confidence.

I started out writing simple tests and that evolved into writing several test suites. During this process, I explored several resources and learned techniques to simplify complicated tasks. One example is to send several dynamically generated inputs into a single request. In this article, I’ll share a few more tips based on my learning.

You may already be familiar with the creation of Postman collections, but if not, I cannot emphasize how easy it is to work with them within the tool. Creating a collection involves identifying the endpoints that you want to test, selecting the method (GET, PUT, POST..), and providing the input either as a parameter or as a body. After the request is sent, the response is displayed in the response body field. Collections allow you to organize your work by grouping related tasks for a module or a project in one place and help maintain your workflow.

Postman

Now that you know how to create postman collections, here are some tips which will make your life as a professional a little bit easier and more enjoyable.

Loop using postman.setNextRequest()

An automated test should always start running tests in a clean environment. It is a common practice to end any postman collection with the tests that clean up data that is created during the test run; you should be able to run any test suite multiple times and expect the same results. If the test suite is interrupted for some reason before running the entire collection (perhaps one of the tests caused an exception that the web service was unable to recover from), then the data clean up would not take place because the tests towards the end of the collection did not execute. The next test run would then also fail and require investigation which is time consuming. To avoid this, clear the data at the beginning of the test run, so that the test always runs on a clean set up and there will not be any false failures.

In this example, at the beginning of the test, using the GET method, all the records are received in the response body. If the length of the response body is “0”, then there are no records in the response. It means there are no data left out from the previous run, hence postman.setNextRequest directs to the beginning of the actual request “ go-to-create-new-vehicle-request”. If the length of the response body from GET Request is “NOT 0” then postman.setNextRequest directs to the DELETE Request “cleanup-vehicles’’ where one or all records will be deleted depending on the endpoint and will loop to GET Request “cleanup-get-veh” using postman.setNextRequest. This loop continues until all the existing data that is not required cleared. Now the set up is ready for a stable test run.

GET Request “cleanup-get-veh”— Tests

var json = JSON.parse(responseBody);
//if there are no vehicles in the account, then execute the next request "go-to-create-new-vehicle-request"
if (json.length === 0){
    postman.setNextRequest("go-to-create-new-vehicle-request");
}
//if there are vehicles in the account, then delete the existing vehicles by executing the DELETE request "cleanup-vehicles"
else{
    postman.setNextRequest("cleanup-vehicles");
}

DELETE Request “cleanup-vehicles”— Tests

postman.setNextRequest("cleanup-vehicles");

Dynamically Generated Request Input

Usually for a request, a hard-coded set of data is used as input. There are some instances where there is a need to provide several dynamically generated random data input for the same request. For example, to create 500 new POIs (places of interest), it would not be practical to hard-code all that data. To trigger the same request multiple times with different data, in the Pre-request, declare a variable “data” with an empty array defined. Use the “for loop” to generate random inputs. These inputs are collected in the array created using the .push() method. This array with the random values has to be converted to as string using JSON.stringify() and assigned to a new variable “data_str”. This variable can be set as an environment variable or global variable “env.places.thistest.body” based on the preference and can be used in the request body.

Pre-request

var data = [];

//Request body was changed in the dev environment based on new requirement
var requestbody_dev = {add: ["veh-id"], remove: []};

//Request body in QA environment
var requestbody_qa = {entityId: "veh-id"};

if (pm.environment.get("env.name") == "dev") {
  data.push(requestbody_dev);
  var data_str = JSON.stringify(requestbody_dev);
  pm.environment.set("env.places.thistest.body", data_str);
} else {
  data.push(requestbody_qa);
  var data_str = JSON.stringify(requestbody_qa);
  pm.environment.set("env.places.thistest.body", data_str);
}

Request Body

postman.setNextRequest("cleanup-get-veh");

Dynamic Request Body by Environment

There are situations where there is a change in the Request body based on the environment (based on new requirements). During this implementation, since the requests are different across environments, the tests will fail. To address this, requests specific to different environments can be defined in the pre-request. For example, Request in “dev” environment is {“add”:[“veh-id”],”remove”:[]}; and the Request in “qa” environment is {“entityId”: (“veh-id”)};

In the pre-request, the requests can be assigned to a variable and using the “IF” statement, depending on the environment in which the test is run, valid request can be used in the test.

Pre-request

var data = [];

//Request body was changed in the dev environment based on new requirement
var requestbody_dev = {"add":["veh-id"],"remove":[]};

//Request body in QA environment
var requestbody_qa = {"entityId": ("veh-id")};

if (pm.environment.get("env.name") == "dev"){
    data.push(requestbody_dev);
    var data_str = JSON.stringify(requestbody_dev);
    pm.environment.set("env.places.thistest.body", data_str);
}
else{
    data.push(requestbody_qa);
    var data_str = JSON.stringify(requestbody_qa);
    pm.environment.set("env.places.thistest.body", data_str);
}

Request Body

{{env.fleetapi.thistest.body}}

Test Differences Between Environments

During an implementation, there might be differences in the test results between “dev” and other environments. It might take a while to merge the code in other environments. To make sure tests pass across all the environments and to avoid seeing failures in the autotest dashboard, tests can be written specific to the environment as shown below. Tests

//dev environment
(pm.environment.get("env.name") =="dev"){
tests["3 edits"] = data.length == 3;
}
//qa Environment
if (pm.environment.get("env.name") =="qa"){
tests["2 edits"] = data.length == 2;
}

Environment Variables Defined in Pre-Request Script

Global environment file can be created for every environment, where every environment file contains variables with the same variable name but different values. These variables can be used in any postman collection. For example, the same variable name “URL” can be set to different values in different environment files and in the postman test, we can just refer to the variable “URL” where needed.

“dev” environment file: var URL = https://dev-environment.example.com

“qa” environment file: var URL = https://qa-environment.example.com

But, environment variables that are applicable to a specific collection can be added to the collection’s pre-request instead of adding to the Global Environment file. If there is any change in the values of the environment variables, updating the values in pre-request is easy compared to updating in all the Global environment files Maintenance of the environment variables are made easy this way.

Pre-request

//dev environment
if (pm.environment.get("env.name") == "dev"){
    pm.environment.set("api.key", "ABC");
}

//qa environment
if (pm.environment.get("env.name") == "qa"){
    pm.environment.set("api.key", "XYZ");
}

//preprod environment
if (pm.environment.get("env.name") == "preprod"){
    pm.environment.set("api.key", "123");
}

Lodash

Last but not the least, an invaluable JavaScript library https://lodash.com/docs/, which helps in writing better tests which are easy to understand, efficient and concise. Here are a few examples

Deep compare 2 values

// Deep Compare between the response body and the expected data
var data = JSON.parse(responseBody);
var data_expected = {
  message: "Successfully deleted vehicle with Id: vehA"
};
tests["match full response body"] = _.isEqual(data, data_expected);

Check to see if the response has the expected data

//Test to check if the response has the expected data
var json = JSON.parse(responseBody);
tests["vehicle object"] = _.find(json, {VehId: "vehA", Name: "vehA"});

Check to see if the response is within a specific range

//Test to check if the response is within a specific range
var resp = JSON.parse(responseBody);
var totalMiles = resp.Miles;
tests["Total Miles"] = _.inRange(totalMiles, 8.2, 8.3) === true;

Recap

Thank you for reading thus far. Hope you enjoyed the content and got to learn a thing or two. Please do not hesitate to ask any questions, add comments or suggestions. At Trimble Maps, we use Postman heavily to automate testing and ensure we deliver high quality software to our customers as efficiently as possible. If you are interested in joining a passionate team doing extraordinary work, please do check our current job openings.

Share this article:

You May Also Like

Experimenting With LangChain AI

| By Ganesan Senthilvel

My recent experiences working with LangChain technology.

New Frameworks Provide New Ways to Create Cross Platform, Cross Mobile Applications

| By Ganesan Senthilvel

My recent experiences working with Flutter and Capacitor.