Postman/Newman 失败重试
Postman / Newman retry in case of failure
在 Newman 中,我想测试以确保响应代码正确、响应时间合理并且响应值正确。
在某些情况下,由于网络问题或其他一些系统条件,一些请求可能会超时或错误的值结束,如果同一请求在几秒钟后处理,这些问题将得到解决。
在这种情况下,我想重试同一个请求 x 次,请求之间有 Y 超时。
如果重试后迭代通过,我希望 Newman 退出代码为 0(成功 运行)。
您可以像这样设置请求工作流程:
创建带有请求的集合,然后:
在预请求选项卡中,您可以实现一个计数器:
// Counter for number of requests
var counter = environment.counter ? _.parseInt(environment.counter) + 1 : 1;
postman.setEnvironmentVariable("counter", counter);
您的测试选项卡将如下所示:
const code = (responseCode.code === 200);
if (code === 200 && environment.counter < X) {
// Stop execution
tests["Status code is 200"] = code;
postman.setNextRequest();
}
else {
// retry the same request
postman.setNextRequest("Name of this request");
}
可以使用 newman CLI 配置请求本身的超时:
newman run myCollection.json --timeout-request Y
几个小时后,我完成了这样一个函数:
function retryOnFailure(successCode, numberOfRetrys) {
var key = request.name + '_counter';
var execCounter = postman.getEnvironmentVariable(key) || 1;
var sleepDuration = 1000;
var waitUntilTime = new Date().getTime() + sleepDuration;
if (responseCode.code !== successCode && execCounter <= numberOfRetrys) {
while (new Date().getTime() < waitUntilTime) {
// Do Nothing -> Wait
}
console.log('Retrying: ' + request.name + '\nGot: ' + responseCode.code + ' Expected: ' + successCode + '\nWaited: ' + sleepDuration / 1000 + 'sec \nRetry Number: ' + execCounter + ' of ' + numberOfRetrys);
execCounter++;
postman.setEnvironmentVariable(key, execCounter);
postman.setNextRequest(request.name);
}
}
用法:
retryOnFailure(404, 4);
这是相同的可重用函数
postmanFunctions.common.retryOnFailure(predicate,retryCount,waitbetweenRetrySec,ReroutetorequestifNeeded ,postmanAssertions);
- 谓词函数决定成败
- 断言函数拥有所有邮递员断言
- 如果重新路由为空,则在重试后执行断言。
- 具有重试次数和等待时间的灵活轮询(如果谓词不再通过
polling/reflow)
- 有一个最大流量计数器(env var),它将流量跳转的次数限制为
避免无限循环
将以下函数存储在 Globals 或 env 中:
() => {
var sleep = (sleepDuration) => {
var startTime = new Date().getTime();
while (new Date().getTime() - startTime < sleepDuration) {}
}
var sleepByAsyncDelayTime = () => {
var sleepDuration = postman.getEnvironmentVariable('asyncDelayTime') || 0;
sleep(sleepDuration);
}
var retryOnFailure = (predicate, numberOfRetrys, sleepDuration, reRouteRequestName, postmanAssertions) => {
var retryCountPerReq_key = request.name + '_retry_count';
var retryCountPerReq = pm.environment.get(retryCountPerReq_key) || 0;
var reflowCountPerReq_key = request.name + '_reflow_count';
var reflowCountPerReq = pm.environment.get(reflowCountPerReq_key) || 0;
var totalReflowCount_key = 'totalReflowCount';
var totalReflowCount = pm.environment.get(totalReflowCount_key) || 0;
var maxReflowCounter = postman.getEnvironmentVariable('maxReflowCounter') || 0;
var maxReflowCounterPerReq = postman.getEnvironmentVariable('maxReflowCounterPerReq') || 0;
function clearAndExit() {
pm.environment.unset(retryCountPerReq_key);
pm.environment.unset(reflowCountPerReq_key);
postmanAssertions();
}
function retry() {
sleep(sleepDuration);
pm.environment.set(retryCountPerReq_key, ++retryCountPerReq);
postman.setNextRequest(request.name);
}
function reFlow() {
if (totalReflowCount < maxReflowCounter && reflowCountPerReq < maxReflowCounterPerReq) {
pm.environment.unset(retryCountPerReq_key);
pm.environment.set(totalReflowCount_key, ++totalReflowCount);
pm.environment.set(reflowCountPerReq_key, ++reflowCountPerReq);
postman.setNextRequest(reRouteRequestName);
} else clearAndExit();
}
if (predicate()) clearAndExit();
else if (retryCountPerReq < numberOfRetrys) retry();
else if (reRouteRequestName != '') reFlow();
else clearAndExit();
}
return {
common: {
sleepByAsyncDelayTime,
sleep,
retryOnFailure
}
};
}
这是我在集合 pre-request 脚本中定义的重试函数。它仅在通过集合执行测试时有效:
Utils = {
wait: function (that, sleepDuration){
that.setTimeout(() => {}, sleepDuration);
},
withRetry: function(that, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, businessRetryConditionCallBack, endRetryCallback){
if (!that.pm.environment.get("collection_tries")) {
that.pm.environment.set("collection_tries", 1);
}
if (((that.pm.response.code != expectedHttpStatus) || businessRetryConditionCallBack())
&& (that.pm.environment.get("collection_tries") <= maxNumberOfTries)) {
var tries = parseInt(that.pm.environment.get("collection_tries"), 10);
that.pm.environment.set("collection_tries", tries + 1);
Utils.wait(that, sleepBetweenTries, maxNumberOfTries);
that.postman.setNextRequest(that.request.name);
} else {
if(businessRetryConditionCallBack()){
// On ne passe pas à la requête suivante
that.postman.setNextRequest(null);
}
that.pm.environment.unset("collection_tries");
endRetryCallback();
}
}
};
下面是如何在 pre-request 请求或测试脚本中使用它:
var expectedHttpStatus = 200;
var maxNumberOfTries = 5;
var sleepBetweenTries = 5000;
Utils.withRetry(this, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, function(){
// Retry business condition callback
return pm.response.json().length <= 0;
}, function(){
// End retry callback
pm.test("Has one result", function () {
pm.expect(pm.response.json().length).to.equals(0);
});
});
只要(http statut 不同于 expectedHttpStatus
或 businessRetryConditionCallBack
为真)且未达到 maxNumberOfTries
且 .
,此代码将重试请求
当 http 状态条件为真且达到 maxNumberOfTries
时,将进行检查以验证 businessRetryConditionCallBack
。如果不为真,收集执行将停止。
在 Newman 中,我想测试以确保响应代码正确、响应时间合理并且响应值正确。
在某些情况下,由于网络问题或其他一些系统条件,一些请求可能会超时或错误的值结束,如果同一请求在几秒钟后处理,这些问题将得到解决。
在这种情况下,我想重试同一个请求 x 次,请求之间有 Y 超时。
如果重试后迭代通过,我希望 Newman 退出代码为 0(成功 运行)。
您可以像这样设置请求工作流程:
创建带有请求的集合,然后:
在预请求选项卡中,您可以实现一个计数器:
// Counter for number of requests
var counter = environment.counter ? _.parseInt(environment.counter) + 1 : 1;
postman.setEnvironmentVariable("counter", counter);
您的测试选项卡将如下所示:
const code = (responseCode.code === 200);
if (code === 200 && environment.counter < X) {
// Stop execution
tests["Status code is 200"] = code;
postman.setNextRequest();
}
else {
// retry the same request
postman.setNextRequest("Name of this request");
}
可以使用 newman CLI 配置请求本身的超时:
newman run myCollection.json --timeout-request Y
几个小时后,我完成了这样一个函数:
function retryOnFailure(successCode, numberOfRetrys) {
var key = request.name + '_counter';
var execCounter = postman.getEnvironmentVariable(key) || 1;
var sleepDuration = 1000;
var waitUntilTime = new Date().getTime() + sleepDuration;
if (responseCode.code !== successCode && execCounter <= numberOfRetrys) {
while (new Date().getTime() < waitUntilTime) {
// Do Nothing -> Wait
}
console.log('Retrying: ' + request.name + '\nGot: ' + responseCode.code + ' Expected: ' + successCode + '\nWaited: ' + sleepDuration / 1000 + 'sec \nRetry Number: ' + execCounter + ' of ' + numberOfRetrys);
execCounter++;
postman.setEnvironmentVariable(key, execCounter);
postman.setNextRequest(request.name);
}
}
用法:
retryOnFailure(404, 4);
这是相同的可重用函数
postmanFunctions.common.retryOnFailure(predicate,retryCount,waitbetweenRetrySec,ReroutetorequestifNeeded ,postmanAssertions);
- 谓词函数决定成败
- 断言函数拥有所有邮递员断言
- 如果重新路由为空,则在重试后执行断言。
- 具有重试次数和等待时间的灵活轮询(如果谓词不再通过 polling/reflow)
- 有一个最大流量计数器(env var),它将流量跳转的次数限制为 避免无限循环
将以下函数存储在 Globals 或 env 中:
() => {
var sleep = (sleepDuration) => {
var startTime = new Date().getTime();
while (new Date().getTime() - startTime < sleepDuration) {}
}
var sleepByAsyncDelayTime = () => {
var sleepDuration = postman.getEnvironmentVariable('asyncDelayTime') || 0;
sleep(sleepDuration);
}
var retryOnFailure = (predicate, numberOfRetrys, sleepDuration, reRouteRequestName, postmanAssertions) => {
var retryCountPerReq_key = request.name + '_retry_count';
var retryCountPerReq = pm.environment.get(retryCountPerReq_key) || 0;
var reflowCountPerReq_key = request.name + '_reflow_count';
var reflowCountPerReq = pm.environment.get(reflowCountPerReq_key) || 0;
var totalReflowCount_key = 'totalReflowCount';
var totalReflowCount = pm.environment.get(totalReflowCount_key) || 0;
var maxReflowCounter = postman.getEnvironmentVariable('maxReflowCounter') || 0;
var maxReflowCounterPerReq = postman.getEnvironmentVariable('maxReflowCounterPerReq') || 0;
function clearAndExit() {
pm.environment.unset(retryCountPerReq_key);
pm.environment.unset(reflowCountPerReq_key);
postmanAssertions();
}
function retry() {
sleep(sleepDuration);
pm.environment.set(retryCountPerReq_key, ++retryCountPerReq);
postman.setNextRequest(request.name);
}
function reFlow() {
if (totalReflowCount < maxReflowCounter && reflowCountPerReq < maxReflowCounterPerReq) {
pm.environment.unset(retryCountPerReq_key);
pm.environment.set(totalReflowCount_key, ++totalReflowCount);
pm.environment.set(reflowCountPerReq_key, ++reflowCountPerReq);
postman.setNextRequest(reRouteRequestName);
} else clearAndExit();
}
if (predicate()) clearAndExit();
else if (retryCountPerReq < numberOfRetrys) retry();
else if (reRouteRequestName != '') reFlow();
else clearAndExit();
}
return {
common: {
sleepByAsyncDelayTime,
sleep,
retryOnFailure
}
};
}
这是我在集合 pre-request 脚本中定义的重试函数。它仅在通过集合执行测试时有效:
Utils = {
wait: function (that, sleepDuration){
that.setTimeout(() => {}, sleepDuration);
},
withRetry: function(that, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, businessRetryConditionCallBack, endRetryCallback){
if (!that.pm.environment.get("collection_tries")) {
that.pm.environment.set("collection_tries", 1);
}
if (((that.pm.response.code != expectedHttpStatus) || businessRetryConditionCallBack())
&& (that.pm.environment.get("collection_tries") <= maxNumberOfTries)) {
var tries = parseInt(that.pm.environment.get("collection_tries"), 10);
that.pm.environment.set("collection_tries", tries + 1);
Utils.wait(that, sleepBetweenTries, maxNumberOfTries);
that.postman.setNextRequest(that.request.name);
} else {
if(businessRetryConditionCallBack()){
// On ne passe pas à la requête suivante
that.postman.setNextRequest(null);
}
that.pm.environment.unset("collection_tries");
endRetryCallback();
}
}
};
下面是如何在 pre-request 请求或测试脚本中使用它:
var expectedHttpStatus = 200;
var maxNumberOfTries = 5;
var sleepBetweenTries = 5000;
Utils.withRetry(this, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, function(){
// Retry business condition callback
return pm.response.json().length <= 0;
}, function(){
// End retry callback
pm.test("Has one result", function () {
pm.expect(pm.response.json().length).to.equals(0);
});
});
只要(http statut 不同于 expectedHttpStatus
或 businessRetryConditionCallBack
为真)且未达到 maxNumberOfTries
且 .
当 http 状态条件为真且达到 maxNumberOfTries
时,将进行检查以验证 businessRetryConditionCallBack
。如果不为真,收集执行将停止。