使用WebdriverJS与CucumberJS时Async/Await异步执行异常问题
解决WebdriverJS + CucumberJS异步步骤乱序执行的问题
嘿,这个问题我之前在项目里也碰到过!明明所有步骤和页面对象都是async/await,结果还是出现步骤“抢跑”的情况——页面还没跳转到第4页,脚本就开始找元素了,直接报错。下面是我踩坑后总结的几个解决方向,你可以逐一排查:
1. 彻底检查步骤定义的异步处理
虽然你说步骤都是async函数,但一定要确保步骤里的每一个异步调用都加了await,而且不要混用回调和async/await。比如:
// 正确的步骤写法 Given('我成功进入第3页', async function () { // 必须await页面对象的异步方法 await this.pageObjects.navigateToPage3(); }); When('我点击跳转至第4页的按钮', async function () { await this.pageObjects.clickPage4Button(); }); Then('我能看到第4页的核心元素', async function () { const targetElement = await this.pageObjects.getPage4TargetElement(); // 对元素的操作也要await expect(await targetElement.isDisplayed()).to.be.true; });
别小看这个,有时候不小心漏掉一个await,就会导致当前步骤还没完成,下一个步骤就开始执行了。
2. 给页面对象加上强等待逻辑
很多时候不是步骤乱序,而是页面加载/跳转的速度跟不上脚本执行速度。这时候不能只依赖driver.findElement(),要主动等待元素或页面状态就绪:
等待元素可见/可交互
在页面对象的元素获取方法里,用driver.wait()包裹操作:
async getPage4TargetElement() { const elementLocator = By.css('#page4-target'); // 先等待元素被定位到 await this.driver.wait(until.elementLocated(elementLocator), 10000); // 再等待元素可见 const element = await this.driver.findElement(elementLocator); await this.driver.wait(until.elementIsVisible(element), 10000); return element; }
页面跳转后等待状态确认
比如点击跳转按钮后,不要立刻执行下一步,要等待URL变化或者页面标志性元素出现:
async clickPage4Button() { const btn = await this.driver.findElement(By.id('go-to-page4')); await btn.click(); // 等待URL包含page4,确认页面跳转完成 await this.driver.wait(until.urlContains('/page4'), 10000); }
3. 检查CucumberJS的配置与版本
- 如果你用的是较旧的CucumberJS版本(比如v2及以下),对async/await的支持可能有bug,建议升级到v3+的稳定版本。
- 确保没有开启并行执行,并行模式会让多个场景同时跑,很容易出现步骤交叉执行的情况。在你的cucumber配置文件(比如
cucumber.js)里确认:
module.exports = { default: { parallel: false, // 必须设为false // 其他配置... } };
4. 排查是否存在未处理的Promise
有时候代码里会不小心留下没有await的异步操作,比如:
// 错误示例:没有await,这个操作会在后台异步执行,不阻塞后续步骤 this.pageObjects.someAsyncMethod(); // 正确做法: await this.pageObjects.someAsyncMethod();
你可以在每个步骤的开头和结尾加日志,打印执行顺序,看看是不是真的步骤在并行执行:
Given('我进入第3页', async function () { console.log('[步骤开始] 进入第3页'); await this.pageObjects.navigateToPage3(); console.log('[步骤结束] 进入第3页'); });
5. 确保Webdriver实例是单例
如果你的测试代码里,每个步骤或页面对象都创建了新的driver实例,会导致多个浏览器窗口同时操作,看起来像是步骤乱序。要保证整个测试流程只使用一个driver实例,比如在hooks里初始化和销毁:
Before(async function () { // 只在测试开始时初始化一次driver this.driver = await new Builder().forBrowser('chrome').build(); }); After(async function () { await this.driver.quit(); });
按照上面的方法逐一排查,应该就能解决步骤“抢跑”的问题了!
内容的提问来源于stack exchange,提问作者VIgnesh
相关产品推荐
相关产品推荐

