Jasmine fit步骤方法执行顺序异常及异步逻辑问题排查
问题根源:异步代码未正确等待导致执行顺序混乱
你遇到的问题核心是Protractor(基于WebDriverJS)的异步特性没有被正确处理。所有和浏览器交互的操作(比如wait、isPresent、click)都是异步的,返回Promise对象,但你的代码没有等待这些异步操作完成就继续执行后续逻辑,同时依赖全局变量finalResult传递状态,这就导致takeDecision在housingLoanWithoutCoApplicant里的异步操作还没完成时就执行了。
分步修复方案
1. 重构getDecision:返回Promise传递状态,移除全局变量依赖
把嵌套的then改成链式调用,让每个异步步骤都返回Promise,最终将决策状态通过Promise resolve传递出来,不再依赖全局变量:
getDecision: function() { // 等待页面可见后,开始判断状态 return browser.wait(protractor.ExpectedConditions.visibilityOf(decisionPage), 60000) .then(() => { // 先判断是否被拒绝 return element(by.xpath(rejectImage)).isPresent(); }) .then((isRejected) => { if (isRejected) { console.log('Application is rejected'); return 'Rejected'; } // 未拒绝则判断是否进入队列 return element(by.xpath(queueImage)).isPresent(); }) .then((isInQueue) => { if (isInQueue) { console.log('Application is sent to underwriter for review'); return 'Queue'; } // 既未拒绝也未进队列,就是批准状态 console.log('Application is approved'); return 'Approved'; }); }
2. 修改returnDecision:返回Promise而非直接读取全局变量
现在returnDecision需要调用getDecision并返回它的Promise,确保拿到的是已经完成异步判断后的状态:
returnDecision: function() { return this.getDecision().then((result) => { console.log('Result is::' + result); return result; }); },
3. 重构takeDecision:用async/await等待异步操作完成
Protractor支持ES6的async/await语法,能让异步代码看起来像同步代码,避免嵌套地狱,同时确保每一步操作完成后再执行下一步:
takeDecision: async function(testData) { // 等待决策状态返回 const decisionStatus = await this.returnDecision(); if (decisionStatus === 'Queue') { if (testData.croDecision.apprvDecision === "Approve") { await utils.sleep(2); const approveButton = await browser.driver.findElement(By.css(croApproveButton)); await approveButton.click(); } else { const declineButton = await browser.driver.findElement(By.css(croDeclineButton)); await declineButton.click(); await utils.sleep(2); await browser.driver.findElement(By.xpath(remarkDecline)).sendKeys('for testing purpose'); } await utils.sleep(2); await browser.driver.findElement(By.linkText("Submit")).click(); await utils.sleep(2); const successMsgElement = await browser.driver.findElement(By.xpath(decisionSuccessMessage)); expect(await successMsgElement.isDisplayed()).toBe(true); } else { console.log("Case is rejected, no further action"); } },
4. 修改Spec文件:确保housingLoanWithoutCoApplicant完成后再调用takeDecision
假设housingLoanWithoutCoApplicant内部也包含异步操作,需要让它返回Promise(或改成async函数),然后在测试用例里用await等待它执行完成:
fit('test', async function() { testData.loan.existingloan = 'No'; // 等待房贷申请流程完全完成 await this.actionwords.housingLoanWithoutCoApplicant(testData); // 再执行决策操作 await this.actionwords.takeDecision(testData); });
核心思路总结
- 永远不要用全局变量传递异步操作的结果,要用Promise的返回值来传递
- 所有涉及浏览器交互的操作必须等待完成(用
then链或async/await) - 确保每个业务函数都返回Promise,这样调用者可以明确等待它执行完毕
内容的提问来源于stack exchange,提问作者rks
相关产品推荐
相关产品推荐

