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:
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.)
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:
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.
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â
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.
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?
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.
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"));
@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_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
@tmccann I think this is where I get lost Iâve pasted a combined image showing 3 different things (the forum would only let me upload a single image )
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:
@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 .
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.