Postman -如何循环请求,直到我得到一个具体的回应?

nszi6y05  于 2022-11-23  发布在  Postman
关注(0)|答案(5)|浏览(372)

我正在用Postman测试API,遇到了一个问题:我的请求发送到某种中间件,因此要么收到一个完整的1000多行JSON,要么收到PENDING状态和空的结果数组:

{
  "meta": {
    "status": "PENDING",
    "missing_connectors_count": 0,
    "xxx_type": "INTERNATIONAL"
  },
  "results": []
}

问题是,如何在Postman中循环这个请求,直到我得到状态SUCCESS和结果array > 0?当我手动一个接一个地发送这些请求时,这是可以的,但当我通过Collection Runner运行它们时,“PENDING”会把一切都搞砸。

ifsvaxew

ifsvaxew1#

我找到了Christian Baumann的awesome post about retrying a failed request,它允许我找到一种合适的方法来解决完全相同的问题,即首先轮询某个操作的状态,只有当它完成时才运行实际的测试。
如果我是你,我最后的代码是:

const maxNumberOfTries = 3; // your max number of tries
const sleepBetweenTries = 5000; // your interval between attempts

if (!pm.environment.get("tries")) {
    pm.environment.set("tries", 1);
}

const jsonData = pm.response.json();

if ((jsonData.meta.status !== "SUCCESS" && jsonData.results.length === 0) && (pm.environment.get("tries") < maxNumberOfTries)) {
     const tries = parseInt(pm.environment.get("tries"), 10);
     pm.environment.set("tries", tries + 1);
     setTimeout(function() {}, sleepBetweenTries);
     postman.setNextRequest(request.name);
 } else {
     pm.environment.unset("tries");

     // your actual tests go here...
}

我喜欢这种方法的地方在于,调用 postman.setNextRequest(request.name) 没有任何硬编码的请求名称。我认为这种方法的缺点是,如果您将此类请求作为集合的一部分运行,它将重复多次,这可能会使您的日志因不必要的噪音而膨胀。
我考虑的另一种方法是编写一个 Pre-request Script,它将进行轮询(通过sending a request)和旋转,直到状态是某种完成。

ruoxqz4g

ruoxqz4g2#

在等待服务就绪或轮询长时间运行的作业结果时,我看到4个基本选项:
1.**使用Postman集合运行器或纽曼并设置每一步的延迟。**此延迟插入到集合中的每一步之间。此处有两个挑战:它可能是脆弱的,除非您将延迟设置为一个请求持续时间永远不会超过的值,并且通常只有少数步骤需要该延迟,而您正在增加总的测试运行时间,从而为公共构建服务器创建过多的构建时间,从而延迟其他挂起的构建。
1.使用https://postman-echo.com/delay/10,其中最后一个URI元素是等待的秒数。这是简单而简洁的,可以在长时间运行的请求之后作为一个步骤插入。挑战是,如果请求持续时间变化很大,您可能会因为等待的时间不够长而得到错误的失败。
1.使用postman.setNextRequest(request.name);重试相同的步骤直到成功。这里的挑战是Postman将尽可能快地执行请求,这可能会对您的服务造成DDoS攻击,将您列入黑名单(并导致错误的失败),如果在普通构建服务器上运行,还会占用大量CPU-减慢其他构建。
1.在预请求脚本中使用setTimeout()。我认为这种方法的唯一缺点是,如果您有多个步骤需要此逻辑,则最终会产生一些需要保持同步的剪切和粘贴代码

注意:这些设置有一些细微的变化-例如在集合、集合文件夹、步骤等上设置它们。

我喜欢选项4,因为它为我的大多数情况提供了正确的粒度级别。注意,这似乎是在Postman脚本中“休眠”的唯一方法。现在不支持标准的javascript休眠方法,如带有async和await的Promise,并且使用沙箱的lodash _.delay(function() {}, delay, args[...])不会使脚本在Pre-request脚本上执行。
在Postman独立应用程序v6.0.10中,将步骤预请求脚本设置为:

console.log('Waiting for job completion in step "' + request.name + '"');

// Construct our request URL from environment variables
var url = request['url'].replace('{{host}}', postman.getEnvironmentVariable('host'));
var retryDelay = 1000;
var retryLimit = 3;

function isProcessingComplete(retryCount) {
    pm.sendRequest(url, function (err, response) {
        if(err) {
            // hmmm. Should I keep trying or fail this run? Just log it for now.
            console.log(err);
        } else {
            // I could also check for response.json().results.length > 0, but that
            // would omit SUCCESS with empty results which may be valid
            if(response.json().meta.status !== 'SUCCESS') {
                if (retryCount < retryLimit) {
                    console.log('Job is still PENDING. Retrying in ' + retryDelay + 'ms');
                    setTimeout(function() {
                        isProcessingComplete(++retryCount);
                    }, retryDelay);
                } else {
                    console.log('Retry limit reached, giving up.');
                    postman.setNextRequest(null);
                }
            }
        }
    });
}

isProcessingComplete(1);

你可以在同一步骤中做你的标准测试。

注意:标准警告适用于使retryLimit变大。

fivyi3re

fivyi3re3#

试试看:

var body = JSON.parse(responseBody);

if (body.meta.status !== "SUCCESS" && body.results.length === 0){
  postman.setNextRequest("This_same_request_title");
} else {
  postman.setNextRequest("Next_request_title"); 
  /* you can also try postman.setNextRequest(null); */  
}
zkure5ic

zkure5ic4#

我正在搜索同一个问题的答案,在阅读您的问题时想到了一个可能的解决方案。每次您没有得到所需的响应时,使用 Postman 工作流重新运行您的请求。无论如何,这就是我要尝试的。

postman.setNextRequest("request_name");

https://www.getpostman.com/docs/workflows

btxsgosb

btxsgosb5#

我没有成功地找到这个问题的完整指导方针,这就是为什么我决定投入一些时间,并从A到Z描述该过程的所有步骤。我将观察一个示例,在该示例中,我们将需要传递事务ID,并在每次迭代中为列表中的下一个事务ID更改查询参数。

步骤1.准备请求

https://某些网址/{{查询参数}}
1.添加{{queryParam}}变量,以便从预请求脚本对其进行更改。
1.如果您需要请求令牌,则应在“授权”选项卡中将其添加到此处。
1.将请求保存到集合(右上角的“保存”按钮)。出于演示目的,我将使用“事务处理请求”名称。稍后我们将需要使用此名称。

步骤2.准备预先请求脚本

在postman中,使用“预请求脚本”选项卡将transactionId变量从查询参数更改为实际事务ID。

let ids = pm.collectionVariables.get("TransactionIds");
ids = JSON.parse(ids);

const id = ids.shift();
console.log('id', id)

postman.setEnvironmentVariable("transactionId", id);
pm.collectionVariables.set("TransactionIds", JSON.stringify(ids));
  • pm.collectionVariables.get* -从集合变量中获取事务ID数组。我们将在步骤4中设置它。
  • ids.shift()* -我们使用它来从id列表中删除我们将要使用的id(以防止对同一个id运行两次)
  • postman.setEnvironmentVariable(“transactionId”,id)* -将事务id从查询参数更改为实际事务id
  • pm.collectionVariables.set(“TransactionIds”,JSON.stringify(ids))* --我们正在建立一个新的变量集合,现在不包括被处理的id。
    步骤3.准备测试

在postman中使用标签Tests来创建一个循环逻辑。测试将在请求执行后执行,因此我们可以使用它来进行下一个请求。

let ids = pm.collectionVariables.get("TransactionIds");
ids = JSON.parse(ids);

if (ids && ids.length > 0){
    console.log('length', ids.length);
    postman.setNextRequest("Transactions Request");
} else {
    postman.setNextRequest(null);
}
  • postman.setNextRequest(“Transactions Request”)* -调用一个新的请求,在本例中它将调用“Transactions Request”请求
    步骤4.运行收集

在 Postman 从左侧栏,你应该选择集合(点击它),然后选择一个选项卡变量.
这是集合变量。在我们的示例中,我们使用TransactionIds作为变量,因此在Current Value中放入要循环的事务ID数组。
现在,您可以单击Run(右上角的按钮,靠近保存按钮)来运行我们的循环请求。
系统将建议您选择要对哪个请求执行操作。请选择我们已创建的请求“事务处理请求”。
它将运行我们的请求与预请求脚本和逻辑,我们已经在测试中设置。最后, Postman 将打开一个新的窗口与我们的运行摘要。

相关问题