邮递员-如何在我收到特定回复之前循环请求?

Mac*_*ski 6 postman web-api-testing postman-collection-runner

我正在用Postman测试API,但遇到了一个问题:我的请求转到了某种中间件,因此我收到了完整的1000+行JSON,或者收到PENDING状态和空数组:

{
  "meta": {
    "status": "PENDING",
    "missing_connectors_count": 0,
    "xxx_type": "INTERNATIONAL"
  },
  "results": []
}
Run Code Online (Sandbox Code Playgroud)

问题是,如何在邮递员中循环此请求,直到获得状态SUCCESS和结果array > 0?当我手动一个接一个地发送这些请求时,可以,但是当我通过Collection Runner运行它们时,“ PENDING”会弄乱所有内容。

Sta*_*nov 8

我发现了一篇关于重试失败请求精彩帖子Christian Baumann 这篇文章让我找到了一种合适的方法来解决完全相同的问题,即首先轮询某些操作的状态,并且只有在它完成后才运行实际测试。

如果我是你,我最终会得到的代码是:

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...
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法的一点是调用postman.setNextRequest(request.name)没有任何硬编码的请求名称。我看到这种方法的缺点是,如果您将此类请求作为集合的一部分运行,它将重复多次,这可能会使您的日志膨胀并产生不必要的噪音。

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


Ste*_*ver 7

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

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

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

我喜欢选项 4,因为它为我的大多数情况提供了正确的粒度级别。请注意,这似乎是 Postman 脚本中“休眠”的唯一方法。现在不支持标准的 javascript 睡眠方法,如带有 async 和 await 的 Promise,并且使用沙箱的 lodash_.delay(function() {}, delay, args[...])不会在预请求脚本上保持脚本执行。

在 Postman 独立应用程序 v6.0.10 中,将您的步骤 Pre-request 脚本设置为:

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);
Run Code Online (Sandbox Code Playgroud)

您可以在同一步骤中进行标准测试。

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

  • 出色的解释;但是,我注意到 setTimeout() 在 Collection 运行中*不*得到尊重。无论等待 10 秒还是 20 秒,它仍然会执行该步骤并继续前进。 (3认同)

Din*_*mar 6

尝试这个:

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); */  
}
Run Code Online (Sandbox Code Playgroud)


小智 3

我正在寻找同一问题的答案,并在阅读您的问题时想到了可能的解决方案。每次未收到所需响应时,使用邮递员工作流程重新运行您的请求。无论如何,这就是我要尝试的。

postman.setNextRequest("request_name");
Run Code Online (Sandbox Code Playgroud)

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