Using dynamic variable values in tests?

In Postman tests, how can I use the actual values of dynamic variables as they were used in the request?

I have a collection with the following in its “Pre-request Scripts”:

pm.globals.set('eventId', 'urn:uuid:{{$guid}}');

Requests in that collection can use that definition in their bodies, for example:

{"id": "{{eventId}}"}

I’ve verified that a valid UUID URN is received by the web service specified by the URL in the request. The web service returns the ID as part of its response. For example:

{"urn:uuid:dd4b63f6-8837-415a-9130-145a4d730cd5":"OK"}

I’ve tried to access that same UUID URN in a test like this:

eventId = pm.variables.get('eventId');

However, when I tried to find that value in the JSON of the response, it always fails, because the value of eventId is the string “urn:uuid:{{$guid}}”, not the actual UUID URN value!

How can I get the actual UUID URN value? Can I somehow get Postman to evaluate the dynamic variable and store its value to the eventId global before the request is sent?

(I’ve found a workaround to get the UUID URN used in the request, but it involves getting the request body and parsing its JSON. It seems like there must be a better way to do this.)

@lsloan_umich

Where is the value for {{$guid}} set ?

@dhoyt, $guid is an internal dynamic variable provided by Postman itself. See: https://www.getpostman.com/docs/postman/environments_and_globals/variables#dynamic-variables

@lsloan_umich

After reading that, I would believe that your best and maybe only solution is to get it from the response body like you are doing.

I hoped that wouldn’t be the case. What I decided to do instead was to set the “event ID” as a global variable in the collection pre-request code:

uuid = require('uuid');
pm.globals.set('eventId', 'urn:uuid:' + uuid.v4());

Then, in each of my requests’ test code, I could retrieve the ID from that variable:

var eventId = pm.globals.get('eventId');

Then I no longer need Postman’s {{$guid}}. As far as I can tell, my code does the same thing as Postman’s internal code when it initializes its “dynamic” variable.

Depending on how my tests grow, I may move the setting of the global variable from the collection level to the folder level.

Hi There,

I’m relatively new to postman and API testing. I’m not able to get this solution to work, and I’m not sure why.

I’ve created a collection that does the following:

  1. Get bearer token
  2. Get a list widgets from the endpoint
  3. Create/POST a new widget using a random widget name
  4. Get a list widgets from the endpoint and test that the newly created widget’s name is returned.

In my collection’s ‘Pre-request Scripts’ tab, I’ve entered this:

uuid = require('uuid');
pm.globals.set('wname', 'widget' + uuid.v4());

Then in my get request (step 4 above), I have this set as one of my tests:

var wname = pm.globals.get('wname');
pm.test("Body matches string", function () {
    pm.expect(pm.response.text()).to.include(wname);
});

This test always fails because I can see that it is looking for a name with a different random number than what was set in the ‘Pre-request Scripts’ above:

AssertionError: expected ‘[{“widget name”:“widgetaac95318-6272-4547-8e4d-974f1cc48616”}]’ to include ‘widgetb6a8ab70-33b9-448a-9a19-0638eee0882e’

Any idea what I may be doing wrong?

Thanks so much for your help and patience.

Ed

Hey @ed_truqc, uuid.v4() would return a new uuid every time so what you’re setting as the global variable would obviously be different from the returned response.

What you can do is that have a dummy request first that gets the list of all widgets and finds the count of current list items, setting the count as a global variable. Then, you can create your new widget, get the global variable and check whether the count has increased or not. You can have a separate test for validating the name to be of the correct format.

Hope this helps.

Thanks so much for your response Deepak. I thought about a count, but I would like to be able to have a random name generated on each run, and have that name carry throughout my test suite. Is there a way to do that?

Thanks again!
Ed

Hey @ed_truqc, try looking into global/environment variables, I do not understand the use case entirely but if you simply want to persist something generated in a request throughout the test suite, you can set that as a global/environment variable in the request that generates it or the initial request and access it in subsequent requests.

Please clarify your question further if this doesn’t help.

Thank you again Deepak, I really appreciate your time.

I thought I was setting my wname variable to a global variable here:

uuid = require('uuid');
pm.globals.set('wname', 'widget' + uuid.v4());

I do this in my collection’s pre-request scripts section. The problem is when I reference the wname variable in my last test:

pm.test("Body matches string", function () {
    pm.expect(pm.response.text()).to.include(pm.globals.get('wname'));
});

‘wname’ is coming back with a different random value. It’s like I’m not storing the global variable correctly, but I can’t figure out why.

Ed

I guess I understand your confusion, as I explained earlier, uuid.v4() would return a new uuid every time, that is why your response text doesn’t include the one you set as your global variable, to verify this behaviour, set something known as the global variable and then log it in the last test. Basically, the uuid you set as the global variable is not the same as the one generated in the response. Hope this helps.

I run into little things like this all the time too and it drives me nuts trying to debug it.

@ed_truqc I just did a little mock up like this using this code in my pre-request script on the call and its generating a new UUID for me each time its run.
It then sets it to an env variable and can be referred to at any time later on.

(function () {
  'use strict';

  var exports = {};

  exports.uuid4 = function () {
    //// return uuid of form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    var uuid = '', ii;
    for (ii = 0; ii < 32; ii += 1) {
      switch (ii) {
      case 8:
      case 20:
        uuid += '-';
        uuid += (Math.random() * 16 | 0).toString(16);
        break;
      case 12:
        uuid += '-';
        uuid += '4';
        break;
      case 16:
        uuid += '-';
        uuid += (Math.random() * 4 | 8).toString(16);
        break;
      default:
        uuid += (Math.random() * 16 | 0).toString(16);
      }
    }
    return uuid;
  };

  //// test
  // Random number gen based on the time stamp
    pm.environment.set("uuid4", exports.uuid4());
    console.log(pm.environment.get("uuid4"));

Hopefully this is somewhat helpful for you.

@tmccann Thanks so much for taking the time to do this! I think I’m following what you’re doing. I added the function to my collection’s pre-request scripts section, and I added the last 2 lines (the test) to my collection’s Tests section. When I tried to run this, I had to make a couple of syntax changes (pasted below). Once I got that squared away and tried to run my collection, I got the following:

ReferenceError: exports is not defined

Here’s how I changed the function code. It was missing a closing brace and a closing paren:

(function () {
  'use strict';

  var exports = {};

  exports.uuid4 = function () {
    //// return uuid of form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    var uuid = '', ii;
    for (ii = 0; ii < 32; ii += 1) {
      switch (ii) {
      case 8:
      case 20:
        uuid += '-';
        uuid += (Math.random() * 16 | 0).toString(16);
        break;
      case 12:
        uuid += '-';
        uuid += '4';
        break;
      case 16:
        uuid += '-';
        uuid += (Math.random() * 4 | 8).toString(16);
        break;
      default:
        uuid += (Math.random() * 16 | 0).toString(16);
      }
    }
    return uuid;
  };
}
);

Thanks again for your time and help, I really appreciate it!

Ed

Oh, you are right @ed_truqc thats my bad.
Looks like I missed something when I did the copy/paste.

Glad this was helpful :slight_smile:

@tmccann Any idea why I’d be getting the ReferenceError: exports is not defined message?

@ed_truqc Are you referring to this function in other calls that do not have it in it?
For example you have Call A that has this in the pre-request tab.
Then have Call B and you are referring to the exports.uuid4() function in the pre-request tab?

You would need the function and the call to it in the same tab.
Set the environment variable pm.environment.set("uuid4", exports.uuid4());
Then anytime you need to use that specific UUID you would refer to it as pm.environment.get("uuid4")

Hope that makes as much sense to you as it does in my head writing it :slight_smile:

@tmccann I think this is where I get lost :wink: I’ve pasted a combined image showing 3 different things (the forum would only let me upload a single image :confused: )

On the left is a screen shot of my collection > edit > Pre-request Script tab. (Note that just below line 32 is where I have the environment set / get you posted in your original response. It’s just not reflected in the screen shot). The middle shows the errors I get at the top of the collection runner when I try to run the collection. And on the right are the errors in the postman console:

I get these errors right off the bat, so none of my tests actually run. Thanks again for your time, help and patience!

Ed

@ed_truqc Give this code a whirl …

(function () {
  'use strict';

  var exports = {};

  exports.uuid4 = function () {
    //// return uuid of form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    var uuid = '', ii;
    for (ii = 0; ii < 32; ii += 1) {
      switch (ii) {
      case 8:
      case 20:
        uuid += '-';
        uuid += (Math.random() * 16 | 0).toString(16);
        break;
      case 12:
        uuid += '-';
        uuid += '4';
        break;
      case 16:
        uuid += '-';
        uuid += (Math.random() * 4 | 8).toString(16);
        break;
      default:
        uuid += (Math.random() * 16 | 0).toString(16);
      }
    }
    return uuid;
  };

  // Random number gen based on the time stamp
    postman.setEnvironmentVariable("uuid4", exports.uuid4());
    console.log(pm.environment.get("uuid4"));
}

());

You should then be able to reference the env variable anywhere in your collection after that and it should work fine.

@ed_truqc I was just looking at some code this morning that I worked on awhile ago and found a function I had that did this and is a bit more simple and hopefully less prone to errors.

//Generate UUID
function generateUUID() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (d + Math.random()*16)%16 | 0;
        d = Math.floor(d/16);
        return (c=='x' ? r : (r&0x3|0x8)).toString(16);
    });
    return uuid;
}

// Random number gen based on the time stamp
pm.environment.set("uuid", generateUUID());
console.log(pm.environment.get("uuid"));

@tmccann I want to thank you for your time and help in understanding this stuff. It can be rare to find someone so willing to help a newbie who’s still trying to figure stuff out, and I want you to know it’s GREATLY appreciated :smile:.

In the course of messing around with my original code, I stumbled onto a way to do exactly what I need in a relatively simple way. I also exported my collection to .json files which made it easier for me to see how all the pieces fit together.

In the end, I used this:

pm.globals.set('wname', 'wname' + Math.floor(Math.random() * 100000000000000));

This command generates a random value for the variable ‘wname’ which holds across all my tests! Sometimes we have to take the long way, eh?

Anyway, thanks again!
Ed

2 Likes