赛普拉斯请求重试 [英] Cypress request with retry
问题描述
在赛普拉斯测试中,我需要通过调用外部API来验证操作.API调用将始终返回结果(来自先前的运行),因此我不能简单地调用一次并验证结果.我需要重试几次,直到找到与当前运行匹配的整体超时/故障.获得当前结果所需的时间差异很大;我真的不能在这个电话会议前花很长时间疯狂.
请参见下面的摘录中的注释;一旦我在一个循环中尝试一个请求,它就永远不会被调用.使用 cy.wait
我得到了相同的结果.我也不能将实际请求包装在另一个返回 Cypress.Promise
或类似功能的函数中,该函数只会将问题推高一个堆栈帧.
In a cypress test, I need to validate an action by calling an external API. The API call will always return results (from some prior run), so I can't simply call once and validate the result. I need to retry some number of times until I find a match for the current run with an overall timeout/failure. The amount of time necessary to get a current result varies greatly; I can't really just put a crazy long wait before this call.
See comments in snippet below; as soon as I try a request in a loop it's never called. I got the same result using cy.wait
. Nor can I wrap the actual request in another function that returns Cypress.Promise
or similar, that just pushes the problem up one stack frame.
Cypress.Commands.add("verifyExternalAction", (someComparisonValue) => {
const options = {
"url": some_url,
"auth": { "bearer": some_apikey },
"headers": { "Accept": "application/json" }
};
//// This works fine; we hit the assertion inside then.
cy.request(options).then((resp) => {
assert.isTrue(resp.something > someComparisonValue);
});
//// We never enter then.
let retry = 0;
let foundMatch = false;
while ((retry < 1) && (!foundMatch)) {
cy.wait(10000);
retry++;
cy.request(options).then((resp) => {
if (resp.something > someComparisonValue) {
foundMatch = true;
}
});
}
assert.isTrue(foundMatch);
});
推荐答案
- 您不能在cy命令之外混合同步(
while
循环;assert.isTrue
...)和异步工作(cy命令).阅读 cypress的介绍#Chains-of-命令 - 您的第一个请求将声明
resp.something
值,如果失败,则整个命令将失败,因此不再重试. - 您正在执行异步工作,因此无法
await
cypress命令(无论如何您都没有这样做),因此您需要递归,而不是迭代.换句话说,你不能使用while
循环.
- You can't mix sync (
while
loop;assert.isTrue
outside the cy commands...) and async work (cy commands). Read introduction to cypress #Chains-of-Commands - Your first request is asserting the
resp.something
value and if it fails the whole command fails, thus no more retries. - You're doing async work and you can't
await
cypress commands (which you weren't doing, anyway) thus you need recursion, not iteration. In other words, you can't use awhile
loop.
喜欢的东西应该可以工作:
Something likes this should work:
Cypress.Commands.add("verifyExternalAction", (someComparisonValue) => {
const options = {
"url": some_url,
"auth": { "bearer": some_apikey },
"headers": { "Accept": "application/json" }
};
let retries = -1;
function makeRequest () {
retries++;
return cy.request(options)
.then( resp => {
try {
expect( resp.body ).to.be.gt( someComparisonValue );
} catch ( err ) {
if ( retries > 5 ) throw new Error(`retried too many times (${--retries})`)
return makeRequest();
}
return resp;
});
}
return makeRequest();
});
如果您不希望赛普拉斯在重试期间记录所有失败的期望,请不要使用抛出的 expect
/ assert
,并进行定期比较(并且可能进行比较)仅在 .then
回调的末尾断言,链接到最后一个 makeRequest()
调用).
If you don't want cypress to log all the failed expectations during retries, don't use expect
/assert
which throws, and do regular comparison (and possibly assert only at the end in a .then
callback chained to the last makeRequest()
call).
这篇关于赛普拉斯请求重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!