重试不稳定的测试
您可以使用 WebdriverIO 测试运行器重新运行某些测试,这些测试由于网络不稳定或竞争条件等原因而变得不稳定。(但是,如果测试变得不稳定,不建议简单地增加重新运行率!)
在 Mocha 中重新运行套件
从 Mocha 的第 3 版开始,您可以重新运行整个测试套件(describe
块中的所有内容)。如果您使用 Mocha,则应优先使用此重试机制,而不是 WebdriverIO 实现,后者仅允许您重新运行某些测试块(it
块中的所有内容)。为了使用 this.retries()
方法,套件块 describe
必须使用未绑定的函数 function(){}
而不是胖箭头函数 () => {}
,如Mocha 文档中所述。使用 Mocha,您还可以使用 wdio.conf.js
中的 mochaOpts.retries
为所有规范设置重试次数。
这是一个示例
describe('retries', function () {
// Retry all tests in this suite up to 4 times
this.retries(4)
beforeEach(async () => {
await browser.url('http://www.yahoo.com')
})
it('should succeed on the 3rd try', async function () {
// Specify this test to only retry up to 2 times
this.retries(2)
console.log('run')
await expect($('.foo')).toBeDisplayed()
})
})
在 Jasmine 或 Mocha 中重新运行单个测试
要重新运行某个测试块,您只需在测试块函数后将重新运行次数作为最后一个参数应用即可
- Mocha
- Jasmine
describe('my flaky app', () => {
/**
* spec that runs max 4 times (1 actual run + 3 reruns)
*/
it('should rerun a test at least 3 times', async function () {
console.log(this.wdioRetries) // returns number of retries
// ...
}, 3)
})
挂钩也一样
describe('my flaky app', () => {
/**
* hook that runs max 2 times (1 actual run + 1 rerun)
*/
beforeEach(async () => {
// ...
}, 1)
// ...
})
describe('my flaky app', () => {
/**
* spec that runs max 4 times (1 actual run + 3 reruns)
*/
it('should rerun a test at least 3 times', async function () {
console.log(this.wdioRetries) // returns number of retries
// ...
}, jasmine.DEFAULT_TIMEOUT_INTERVAL, 3)
})
挂钩也一样
describe('my flaky app', () => {
/**
* hook that runs max 2 times (1 actual run + 1 rerun)
*/
beforeEach(async () => {
// ...
}, jasmine.DEFAULT_TIMEOUT_INTERVAL, 1)
// ...
})
如果您使用的是 Jasmine,则第二个参数保留用于超时。要应用重试参数,您需要将超时设置为其默认值 jasmine.DEFAULT_TIMEOUT_INTERVAL
,然后应用您的重试次数。
此重试机制仅允许重试单个挂钩或测试块。如果您的测试附带了一个挂钩来设置您的应用程序,则不会运行此挂钩。Mocha 提供原生测试重试来提供此行为,而 Jasmine 则没有。您可以在 afterTest
挂钩中访问已执行的重试次数。
在 Cucumber 中重新运行
在 Cucumber 中重新运行完整套件
对于 cucumber >=6,您可以提供retry
配置选项以及一个可选的 retryTagFilter
参数,以使所有或某些失败的场景获得额外的重试,直到成功。为了使此功能正常工作,您需要将 scenarioLevelReporter
设置为 true
。
在 Cucumber 中重新运行步骤定义
要为某个步骤定义定义重新运行率,只需对其应用重试选项,例如
export default function () {
/**
* step definition that runs max 3 times (1 actual run + 2 reruns)
*/
this.Given(/^some step definition$/, { wrapperOptions: { retry: 2 } }, async () => {
// ...
})
// ...
})
重新运行只能在您的步骤定义文件中定义,而不能在您的功能文件中定义。
在每个规范文件的基础上添加重试
以前,只有测试和套件级别的重试可用,在大多数情况下这很好。
但在任何涉及状态的测试(例如服务器或数据库中的状态)中,第一次测试失败后状态可能会变为无效。由于它们将以无效状态开始,因此任何后续重试都可能没有通过的机会。
为每个规范文件创建一个新的 browser
实例,这使得它成为挂钩和设置任何其他状态(服务器、数据库)的理想位置。此级别的重试意味着整个设置过程将简单地重复,就像它是针对新规范文件一样。
export const config = {
// ...
/**
* The number of times to retry the entire specfile when it fails as a whole
*/
specFileRetries: 1,
/**
* Delay in seconds between the spec file retry attempts
*/
specFileRetriesDelay: 0,
/**
* Retried specfiles are inserted at the beginning of the queue and retried immediately
*/
specFileRetriesDeferred: false
}
多次运行特定测试
这有助于防止代码库中出现不稳定的测试。通过添加 --repeat
cli 选项,它将运行指定的规范或套件 N 次。使用此 cli 标志时,还必须指定 --spec
或 --suite
标志。
在向代码库添加新测试时,尤其是在通过 CI/CD 过程添加新测试时,测试可能会通过并被合并,但后来变得不稳定。这种不稳定性可能来自许多方面,例如网络问题、服务器负载、数据库大小等。在您的 CD/CD 过程中使用 --repeat
标志可以帮助您在这些不稳定的测试合并到主代码库之前捕获它们。
一种策略是在您的 CI/CD 过程中像往常一样运行您的测试,但是如果您要引入一个新的测试,那么您可以运行另一组测试,其中在 --spec
中指定了新的规范以及 --repeat
,以便它运行新的测试 x 次。如果测试在任何这些时间都失败,则测试将不会被合并,并且需要查看其失败的原因。
# This will run the example.e2e.js spec 5 times
npx wdio run ./wdio.conf.js --spec example.e2e.js --repeat 5