邮递员 - 如何循环请求直到我得到特定的响应?

Posted

技术标签:

【中文标题】邮递员 - 如何循环请求直到我得到特定的响应?【英文标题】:Postman - how to loop request until I get a specific response? 【发布时间】:2017-09-03 20:10:28 【问题描述】:

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


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

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

【问题讨论】:

相关:***.com/q/64938456. 【参考方案1】:

我找到了 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) 没有任何硬编码的请求名称。我看到这种方法的缺点是,如果您将此类请求作为集合的一部分运行,它将被重复多次,这可能会使您的日志因不必要的噪音而膨胀。

我正在考虑的替代方法是编写一个 预请求脚本,它将执行轮询(通过 sending a request)并旋转直到状态为某种完成。这种方法的缺点是同一逻辑需要更多代码。

【讨论】:

【参考方案2】:

在等待服务准备好或轮询长时间运行的作业结果时,我看到了 4 个基本选项:

    使用 Postman 收集运行器或 newman 并设置每步延迟。此延迟插入到收集的每个步骤之间。这里有两个挑战:它可能很脆弱,除非您将延迟设置为请求持续时间永远不会超过的值,并且通常只有少数步骤需要延迟,并且您正在增加总测试运行时间,从而为延迟其他待处理构建的通用构建服务器。 使用https://postman-echo.com/delay/10,其中最后一个 URI 元素是等待的秒数。这简单明了,可以在长时间运行的请求之后作为单个步骤插入。挑战在于,如果请求持续时间差异很大,您可能会因为等待时间不够长而出现错误的失败。 使用postman.setNextRequest(request.name);重试相同步骤直到成功。这里的挑战是 Postman 将尽可能快地执行请求,这可以对您的服务进行 DDoS 攻击,将您列入黑名单(并导致错误的故障),如果在通用构建服务器上运行会消耗大量 CPU - 减慢其他构建。 在预请求脚本中使用 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 变大。

【讨论】:

很好的解释;但是,我注意到 setTimeout() not 在 Collection 运行中得到尊重。不管是等待 10 秒还是 20 秒,它仍然只是运行该步骤并继续前进。 @Guy,你找到运行收藏的解决方法了吗? @duyn9uyen 哇,这已经快一岁了!从那以后我继续前进;这些天我什至没有那么多使用邮递员。不是因为我不喜欢它,只是我有不同的任务。不过谢谢你。 对于其他人,我不使用 setTimeOut(),而是使用 postman.setNextRequest() 的组合来控制接下来调用哪些端点并发布到 postman-echo.com/delayint 来等待.【参考方案3】:

试试这个:

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); */  

【讨论】:

【参考方案4】:

我正在寻找相同问题的答案,并在阅读您的问题时想到了可能的解决方案。 每次您没有得到所需的响应时,使用邮递员工作流程重新运行您的请求。不管怎样,这就是我要尝试的。

postman.setNextRequest("request_name");

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

【讨论】:

以上是关于邮递员 - 如何循环请求直到我得到特定的响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何从邮递员的响应标头中提取特定的字符串值?

如何获得响应消息? NodeJs、ReactJs、邮递员

如何增加 Postman 客户端请求超时

如何修复我的代码以使其发送 json 数据作为对邮递员 GET 请求的响应?

axios在20秒内给出响应,但具有相同请求有效载荷的相同api在6秒内从邮递员那里得到响应

邮递员 - 如何使用环境变量“responseBody.has”?