Cucumber JS step definition timeout 设置不生效
结论
在支持 step 级超时配置的 Cucumber-JS 版本中,{ timeout: 30 * 1000 } 的写法是正确的。timeout 的单位是毫秒,因此这里表示 30 秒。
如果测试仍然总是在 15 秒时失败,触发的通常不是当前 step 的 Cucumber 超时,而是 confirmation.isDisplayed() 内部或浏览器自动化框架设置的 15 秒等待超时。也可能是项目使用的 Cucumber-JS 版本较旧,不支持 step 级配置。
推荐设置方式
可以先在 Cucumber support 文件中设置全局默认超时:
const { setDefaultTimeout } = require('@cucumber/cucumber');
setDefaultTimeout(30 * 1000);
使用 ES Module 时:
import { setDefaultTimeout } from '@cucumber/cucumber';
setDefaultTimeout(30 * 1000);
这段代码需要在场景执行前加载,一般放在 features/support 下的初始化文件中。
如果当前版本支持 step 级 timeout,也可以保留单独配置:
Then(
/^The "(.*)" page is displayed$/,
{ timeout: 30 * 1000 },
async function (name) {
let result;
switch (name.toLowerCase()) {
case 'home':
result = await confirmation.isDisplayed();
break;
default:
throw new Error('Please specify a valid page name: ' + name);
}
expect(result).to.equal(true);
}
);
检查真正超时的位置
先查看失败信息和调用栈。如果错误类似:
function timed out, ensure the promise resolves within 15000 milliseconds
超时一般来自 Cucumber。
如果错误中出现以下关键词,则更可能是浏览器驱动或等待方法超时:
waitUntil
waitForDisplayed
element was not displayed
TimeoutError
condition timed out
此时只提高 Cucumber timeout,并不会延长 confirmation.isDisplayed() 内部的等待时间。例如,该方法内部可能设置了 15 秒超时:
async isDisplayed() {
await confirmationElement.waitForDisplayed({
timeout: 15 * 1000
});
return confirmationElement.isDisplayed();
}
需要修改实际等待操作的 timeout:
async isDisplayed() {
await confirmationElement.waitForDisplayed({
timeout: 30 * 1000
});
return confirmationElement.isDisplayed();
}
也可以让页面对象接收 timeout:
async isDisplayed(timeout = 30 * 1000) {
await confirmationElement.waitForDisplayed({ timeout });
return confirmationElement.isDisplayed();
}
然后在 step 中明确传入:
result = await confirmation.isDisplayed(30 * 1000);
具体使用哪种等待 API,取决于项目采用的是 WebdriverIO、Selenium、Playwright、Protractor 还是其他框架。不同框架的参数名称不能直接混用。
版本兼容问题
如果当前 Cucumber-JS 版本不支持下面这种重载形式:
Then(pattern, { timeout: 30000 }, implementation);
第二个参数可能不会按预期生效。这种情况下,应改用该版本提供的全局设置方式:
setDefaultTimeout(30 * 1000);
还要确认项目没有混用旧包名和新包名,例如同时存在:
require('cucumber');
require('@cucumber/cucumber');
setDefaultTimeout、Then 和实际执行测试的 CLI 应来自同一套 Cucumber 包。否则,超时设置可能应用到了另一份模块实例上。
注意事项
Cucumber timeout 和页面等待 timeout 是两层不同的限制:
- Cucumber timeout 控制整个 step 最长可以执行多久。
- 页面或元素等待 timeout 控制元素、页面状态或浏览器条件最长等待多久。
如果 payment 最长需要约 20 秒,通常应满足:
元素等待 timeout > payment 的合理最长处理时间
Cucumber step timeout > 元素等待 timeout
例如,可以将页面等待设为 30 秒,将 step timeout 设为 35 秒。不要只增加固定延时。等待 confirmation page 的明确状态或元素出现,通常更稳定。
备注:内容仅供参考。
