Next-Level Automation Tricks for Newman
Newman is Postman’s tool that allows you to run collections of requests, and their associated scripting, from the command line. And yes, it is named after the character in the comedy series “Seinfeld,” portrayed by actor Wayne Knight.
When I recently livestreamed on Twitch about building a chat bot to interact with people watching my “learning in public” broadcasts, I wanted to make some chat commands that would retrieve data from API endpoints—like fetching a joke, or the weather in a given location. Yes, it would have been easier just to call those APIs directly from the codebase where I wrote my bot, but I wanted to explore how to use Newman in new and interesting ways. In this blog post, I’ll share how I used Newman to power my chat bot.
There are two general ways to run Newman. A common method is to export your environments and collections in JSON format and using those files for Newman to run these endpoints whenever you like. The second method uses the Postman API to fetch collections and environments described in this post.
Examining output from Newman
If you have test code written within your requests in Postman, Newman shows whether your tests passed or not, or at a minimum, it will just call your requests. If your pre-request scripts or test scripts have syntax errors, Newman will show some error responses as well.
Having a command-line tool for Postman makes it a great asset to teams who utilize continuous integration systems. Your team can create some interesting scripting with branch logic and test a variety of data to your collections.
For example, Newman will exit with a status code that you can capture in the command line if something fails. Most continuous integration systems will watch for these exit codes and pass or fail your CI build accordingly. To see this yourself using bash or zsh, you can run echo $?
to see the exit code. Here’s an example of calling a collection where I did not pass my API key properly, and Newman showed the assertion error in my test code, and exited with a code of “1.”
Fetching data programmatically
Automating things with Newman is much easier when you can fetch collections or environments from Postman in a programmatic way. You can call the Postman API endpoints to fetch a collection using your Postman API key. This is far more convenient than exporting your collections, environments, etc, every time you make a change, but you will need your system to be able to fetch data from the Postman servers through an internet connection. On the other hand, exporting your collections, etc, while less convenient every time you make a change, allows you to work within confined/restricted network environments.
Postman strongly recommends that you follow good security practices to protect your API keys and other private information. For example, using protected data storage or environments with restricted access to keep sensitive data away from people or processes which should not have permission to view that data.
To get started with programmatic fetching, you will need to know your collection ID and environment ID, and you can get those from the Postman app. You could also grab your entire workspace by its ID and programmatically scan through that for multiple environments or collections as well, but that will require more steps.
Start by clicking on the collections icon, select the collection you wish to use in Newman, then click on the (i) information icon where you’ll see the collection ID value. Similarly, click on the environments icon on the left, choose which environment you’d like to fetch with Newman, and get the environment ID in a similar way.
Once you know your collection ID and your Postman API key, we can fetch the collection on the command line using Newman. In this example, I’m using shell environment variables to fetch my collection and my environment:
export POSTMAN_COLLECTION_URL="https://api.getpostman.com/collections" export POSTMAN_ENV_URL="https://api.getpostman.com/environments" export NEWMAN_COLLECTION_UID="abc-123-def-123456789" Export NEWMAN_ENVIRONMENT_UID="ace-987-bdf-7654321" export NEWMAN_POSTMAN_APIKEY="def789-abc1-3d4f5a6b7c" newman run \ "$POSTMAN_COLLECTION_URL/$NEWMAN_COLLECTION_UID?apikey=$NEWMAN_POSTMAN_APIKEY" \ -e "$POSTMAN_ENV_URL/$NEWMAN_ENVIRONMENT_UID?apikey=$NEWMAN_POSTMAN_APIKEY"
A quick note about fetching environments
Fetching environments from Postman will only fetch your “initial values,” and not your “current values.” Postman does not synchronize your “current values” with the Postman server-side data storage, so you can securely keep your sensitive data on your own systems. Since we recommend setting environment values to a “secret” type, and only using the “current value” field, for sensitive data like API keys, the environment export will return an empty value. This could cause things to fail if your collection requests are expecting a “current value” to be set in a given environment.
Controlling collection runs with subfolders
While it’s not possible to tell Newman to run a single request in a collection, you can organize your collection into subfolders, then tell Newman to only run that particular folder of requests. You can use the “folder” option for this:
newman run "$POSTMAN_COLLECTION_URL/$NEWMAN_COLLECTION_UID?apikey=$NEWMAN_POSTMAN_APIKEY" --folder FolderName
Now, when Newman calls your collection, it will only execute the requests within that particular folder.
Note: Postman and Newman will run your collection by running any requests found in subfolders first, in the order it finds the folders, and then in whichever order the requests are found in those folders. Once any subfolders have been run, Postman and Newman will then run any remaining requests.
For example, in a collection that uses this subfolder layout:
Postman, and Newman, would open “folder1,” run any pre-request scripts, then see “subfolder1,” run its pre-request scripts, and execute the request for “request 2” and “request 3,” then run any remaining “test” code for “subfolder 1” and only then run “request 1.” Postman will currently run through all subfolders first, and then any remaining requests, when examining a folder.
Reducing duplicated effort
If you have a complex set of subfolders of requests that share some common requests, it would be great to apply the “Don’t Repeat Yourself” (DRY) principle here to avoid duplication.
Let’s set up a new example: requests for “ABC” and “DEF” are separate test cases, but both need an authentication token. We could set up a new folder with that authentication call first, and reorganize our folders in this way:
Unfortunately, if we tell Newman to run “folder1,” it will execute all three of our subfolders:
My first instinct was to set a global variable in Newman, telling my “get auth token” request to use postman.setNextRequest()
to call a particular subfolder, but Postman does not currently allow the collection runner to set the “next” request to a request outside of the folder where the instruction was found. In the above diagram, “request ABC” cannot use “setNextRequest” to move to “request DEF,” because these requests exist in different subfolders.
Also, since Postman lists folders first, and then requests, we can’t easily set these up in a way that lists the “get auth token” request ahead of the subfolders.
Working smarter with pre-request scripts
One way forward from here would be to set the auth token request work in a folder-level pre-request script. Yes, even subfolders can have pre-request and test code, just like at a collection level. A scenario here, then, would be a setup like this:
Then, follow these steps:
- Click on “folder1” and set the authentication work in a pre-request script. For example, you can use the snippet for “Send a request” to generate this code for you.
- Save the result of that request as a variable using
pm.variables.set(“variable name,” “value”)
- For the requests in your subfolders, you now have access to variable called “variable name.”
To see this visually, I have set my pre-request script of “folder 1” to the following code:
I have then set a parameter in my “request DEF” to use my variable called “ian” as a parameter value:
And now we can tell Newman to only run “subfolder 2,” as all pre-request code and test code from lower-level folders will also execute along the way. In this case, because “subfolder 2” is within “folder1,” the “folder1” pre-request code will execute first.
In the output, we see that “parameter1” is successfully using the “was here” string set in the folder1 pre-request script.
Passing variables to Newman
As mentioned above, you can pass variables to Newman using the “–global-vars” flags, and you can repeat that switch over and over to set many variables. Below, I’m setting two global variables called “var1” and “var2”:
newman run "$POSTMAN_COLLECTION_URL/$NEWMAN_COLLECTION_UID?apikey=$NEWMAN_POSTMAN_APIKEY" --global-vars "var1=value1" --global-vars "var2=value2"
Setting variables on the command line is a great way to manage some if/else branch logic in your tests to have Newman run very complex operations.
How I used all of this for my Twitch chat bot
When my Twitch chat bot sees a user type a chat command like “!dadjoke,” it will call my Postman Collection, and use a folder name that I have mapped in my chat bot software. For example, I might make a Postman Collection subfolder called “dadjoke,” and it will execute the request within, and give back the data to my Twitch Bot which then sends the result to my viewers.
If Newman only tells you whether tests passed or not, how do I get that data back from Newman?
Related: Postman Collection best practices
Getting data from Newman
There are two ways to get data out of Newman. One way feels more like a hack and has some restrictions.
1. Hacking console.log
Our friend, console.log()
: the debugging tool of choice of many developers.
If you use console logging in your Postman scripts, Newman will show you the output messages, but they are surrounded by ASCII lines that wraps around the data on the left edge, as seen in the image below.
You could parse that information out using regular expressions or other string matching, but the ASCII markers can be tricky to deal with when you have very long lines of text wrapping in your console.log()
output.
To better facilitate this, we can build a JavaScript “runner” script, which imports Newman as a library call, and capture all console.log()
events by subscribing to the “console” event in JavaScript. You can look at the NPM documentation to see all of the events that Newman can attach to, which will also allow you to add additional work before pre-request scripts, or if exceptions are thrown, and more.
It might be easier to write a JavaScript runner script that runs Newman as a library call, and capture its console.log output by subscribing to the “console” event, and writing your own custom logging. Here’s an example from a Postman user that you can reference. You can also reference our Newman API for more information and context.
2. Custom reporters
A better way of catching data, though, is using Custom Reporters. This takes more effort, because it will require you to publish a package using “npm publish.” If your organization has its own npm registry you can publish your package there, or you can use “scoped” package names. Using scoped package names will allow you to publish a “private” package, but requires a paid npm account.
Learn more about Newman
If you’d like to get started with Newman, you can check out our introduction to Newman, which is part of our 30 Days of Postman challenge. You’re welcome to fork my API Twitch Chat Bot collection if you’d like to try some of these tips yourself! Fork the collection, and run it for the folder called “folder 1” in Newman with your own Postman API key. The console output you see shows the progression of pre-request scripts and test scripts from each of the folder levels and requests.
Technical review by Sean Keegan.
What do you think about this topic? Tell us in a comment below.