I'd like to chain several Newman collection test runs. In my particular case, the first test run needs to pass some data to the second test run. How would I go about this?
In my current (not working) solution, I set a object in the global variables used by newman and pass that data to a variable accessible to the second test run. I noticed the newman run only got triggered after running through all the code. I figured I could try using a Promise
to make the code wait until the first test run is finished before doing the second test run.
This is what I currently have:
var output
let run1 = new Promise(function (onResolve, onReject){
let out
let error
newman
.run({ /* options like collection etc go here */ })
.on('done', function (err, summary) {
if(err) {
error = err
}
out = summary.globals.values.members.find(item => /* some query here */).value
})
if(out){
onResolve(out);
} else{
onReject(error);
}
})
run1.then(
//when "onreslove" got triggered
function(value) {
console.log('test run successful')
output = value
},
//when "onReject" got triggered
function(error){
console.log('test run failed with error!\n')
console.log(error)
return
}
)
if (output){
let run2 = new Promise(function(onReslove, onReject) {
let error
let testData = require(/* path to json test data file*/)
//some logic here that adds the data from the output variable to the "testData" object.
newman.run({ /* some options here */})
.on('done', function (err, summary) {
if (err) {
console.log(err)
error = err
}
})
if(!error){
onResolve();
} else{
onReject(error);
}
})
run2.then(
//when onResolve got triggered
function() { console.log(`test run successful`)},
//when onReject got triggered
function(error) {
console.log('test run failed with error!\n')
console.log(error)
return
}
)
} else{
console.log(`Expected output value, received ${output} instead.`)
}
I'm currently stuck, out
will always be undefined
because the "done" event didn't trigger yet at the time my debug session reached if(output){
.
According to the API Reference, newman.run
accepts a callback function. This callback function can than be used to initiate a second, nested run.
newman.run(
{ /* test run options */ },
function(err, summary){
console.log('first run finished')
if (err) {
console.log(err)
return
}
let output = summary.globals.values.members.find(/* some array query */).value
let testData = require(/*path to test data json file*/)
//some logic here to add the output to the testData for the next run
newman.run(
{/* test run options */},
function(err, summary){
if (err) {
console.log(err)
return
}
console.log('second run finished')
}
)
})
Subsequent newman test runs can be chained by the .then
callback of a promise that did a test run:
function newmanRun(options) {
return new Promise(function(onResolve){
newman
.run(options)
.on('done', function (err, summary) {
if (err) {
console.log(`\ntest run failed!\n${err}`)
return
}
console.log(`\ntest run succeeded!\n`)
onResolve(summary)
})
})
}
function run1() {
let options = { /* newman test run options */ }
newmanRun(options).then(
//when "onResolve" got triggered
function(summary) {
let output = summary.globals.values.members.find(/*query here*/).value
run2(output)
}
)
}
function run2(input){
let testData = {}//path to test data file
// some logic here to pass the output data from the previous run as input for the next test run.
let options = { /* use your test data variable in the newman options object*/ }
newmanRun(options).then(
//when "onResolve" got triggered
function(summary) {
console.log('test run finished.')
}
)
}
//now we just need to call the run1 function to start the test run chain:
run1()
I personally think this is the cleanest way since it doesn't involve nesting one test run into another.
/**
* Returns a promise to do a newman test run with the provided options. Use the `.then()` method to execute any callback function when the test run completed.
* @param {Object} options See https://github.com/postmanlabs/newman#api-reference for details on the options object.
* @returns {Promise} When the promise is fulfilled, a callback function with newman run summary as argument gets called.
*/
async function newmanRun(options) {
return new Promise(function(onResolve){
newman
.run(options)
.on('done', function (err, summary) {
if (err) {
console.log(`\ntest run failed!${err}`)
return
}
console.log(`\ntest run succeeded!`)
onResolve(summary)
});
})
}
async function run1(data) {
//create the newman options here, e.g. data file, collection to run, etc...
let options = { /* pass your data from the function parameter to the options here */ }
return newmanRun(options) //returns a promise
}
async function run2(data){
//create the newman options here, e.g. data file, collection to run, etc...
let options = { /* pass your data from the function parameter to the options here */ }
return newmanRun(options) //returns a promise
}
async function start(){
//load the test data and start iterating the newman test run chain.
let input = JSON.parse(readFileSync(/** path to yor data file here */))
summary = await run1(/* pass the data from input variable here */)
output = summary.globals.values.members.find(/* query to fetch whatever data returned from the test run */).value
await run2(/* the data from output here as input for the next test run*/)
}
start()