更多想法:
即时重试更改
TLDR
优点:简单
缺点:使用内部命令
有一个内部命令可让您在测试中更改重试次数。
我强调内部这个词是为了警告它可能会在某些新版本中停止工作。
使用您的代码
export class Login {
...
login(email, password) {
const originalRetries = cy.state('runnable')._retries
cy.state('runnable')._retries = 5 // WARNING - internal command
this.username_input().type(email);
...
cy.state('runnable')._retries = originalRetries // restore configured retries value
}
}
递归重试
TLDR
优点:适用于不稳定的情况
缺点:需要显式等待
如果您想要更长但更主流的解决方案,请使用递归。
您将需要一个非失败检查来处理重试或完成逻辑,这实际上意味着将 cy.get('.profile-content').should('exist') 更改为 jQuery 等效项并使用显式等待(此模式的缺点)。
export class Login {
...
loginAttempt(attempt = 0) {
if (attempt === 3) throw 'Unable to login after 3 attempts'
this.login_button().click();
// wait for login actions to change the page
cy.wait(200).then(() => {
// test for success
if (Cypress.$('.profile-content').length > 0) {
return // found it, so finish
}
// retry
loginAttempt(email, password, ++attempt)
})
}
login(email, password) {
this.username_input().type(email);
this.password_input().type(password);
loginAttempt()
return this
}
}
您可以将cy.wait(200) 降低一点并提高最大尝试次数,例如cy.wait(20) 和if (attempt === 300)
缺点是每次重试都会占用更多的堆内存,因此过分使用会造成不利影响 - 您需要进行试验。
直接设置登录状态
TLDR
好处:绕过测试的片状部分
缺点:需要了解登录状态
您可能会考虑的另一个方面是完全消除不稳定的登录。为此,您需要找出应用程序认为已登录的内容。是cookie、localstorage值等吗?
对于每个需要处于登录状态但实际上并未测试登录过程的测试,直接设置该状态。
这里给出一个例子recipes - logging-in__using-app-code
describe('logs in', () => {
it('by using application service', () => {
cy.log('user service login')
// see https://on.cypress.io/wrap
// cy.wrap(user promise) forces the test commands to wait until
// the user promise resolves. We also don't want to log empty "wrap {}"
// to the command log, since we already logged a good message right above
cy.wrap(userService.login(Cypress.env('username'), Cypress.env('password')), {
log: false,
}).then((user) => {
// the userService.login resolves with "user" object
// and we can assert its values inside .then()
// confirm general shape of the object
expect(user).to.be.an('object')
expect(user).to.have.keys([
'firstName',
'lastName',
'username',
'id',
'token',
])
// we don't know the token or id, but we know the expected names
expect(user).to.contain({
username: 'test',
firstName: 'Test',
lastName: 'User',
})
})
function login (username, password) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
}
return fetch(`${config.apiUrl}/users/authenticate`, requestOptions)
.then(handleResponse)
.then((user) => {
// login successful if there's a jwt token in the response
if (user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('user', JSON.stringify(user))
}
return user
})
}