I’ve seen a few posts now where the poster would like to run all of the requests in a collection\folder, but needs to run a particular request in the collection\folder x number of times using a data driven approach.
Currently with Postman, the whole collection\folder will run once for each line in the CSV or JSON file.
Typical use case would be where the tester wants to authenticate once and then run x number of tests after authentication.
There might be two or three steps that need to happen before the data driven test needs to run.
This means that pre-requests scripts are not always going to work (or can get complicated to code).
The approach I’ve taken to this is to add the test data as JSON to a single cell in a CSV data file and to import that into an array that I can loop though with sendRequest. (Basically the reverse of using the pre-request script).
For this showcase, I’m just using a simple JSON structure with username\password fields and will be running the tests against Postman echo.
Initial JSON structure.
{"TestData":[
{ "Username":"TestUserOne", "Password":"PasswordOne" },
{ "Username":"TestUserTwo", "Password":"PasswordTwo" },
{ "Username":"TestUserThree", "Password":"PasswordThree" }
]}
I would recommend using https://jsonformatter.org/ or similar to minify the JSON, which I’ve then stored in my CSV file as a single element.
First two lines in the Test tab will import the file and parse the data into a JavaScript object.
var jsonString = data.json;
var jsonObject = JSON.parse(jsonString);
I then use a helper function to convert this to an array.
This is a personal preference, you could probably use a for loop with the JavaScript object and forgo this step.
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else
//if key matches and value matches or if key matches and value is not passed (eliminating the case where key matches but passed value does not)
if (i == key && obj[i] == val || i == key && val == '') { //
objects.push(obj);
} else if (obj[i] == val && key == ''){
//only add if the object is not already in the array
if (objects.lastIndexOf(obj) == -1){
objects.push(obj);
}
}
}
return objects;
}
To turn the test data into an array, using the helper function and the JavaScript map function.
var array = (getObjects(jsonObject,'Username','')).map(({ Username, Password }) => ({ Username, Password }));
A quick test to ensure that we have an array that is not empty.
pm.test("Array check", () => {
pm.expect(array).to.be.an("array").that.is.not.empty;
});
Finally, I have a ForEach look using sendRequest with the tests in the loop.
// ForEach loop with a sendRequest and tests.
array.forEach(element => {
pm.sendRequest({
// I'm just sending the Username from the test data
url: 'https://postman-echo.com/get?Username=' + element.Username,
method: 'GET',
}, function (err, res) {
if (err) {
console.log(err);
} else {
// define the expectedResponse because we can also use this to format the test name.
var expectedResult = element.Username;
// define the actual result, which will be the username from the response
var actualResult = res.json().args.Username;
// Our actual test
pm.test(`Username = ${expectedResult}`, () => {
pm.expect(actualResult).eql(expectedResult);
});
}
});
});
Running this through the collection runner with the CSV file the Data File.
You can see that the sendRequest has been sent three times (once for each of the test users).
With tests that are passing. (with relevant test names).