当隐式等待小于显式时会发生误解:
var timeOut = 5000;
var search = element(by.xpath(`//*[@name='qwer']`));
browser.manage().timeouts().implicitlyWait(4000);
browser.ignoreSynchronization = true;
describe('Protractor Test', function () {
beforeEach(function () {
browser.get('https://www.google.com.ua');
});
it('EC', function () {
console.log('START');
// browser.sleep(timeOut);
browser.wait(protractor.ExpectedConditions.presenceOf(search), timeOut);
});
});
总时间:8.613秒。隐式设置等待第二个低位:3000,结果为6.865秒。它是如何在引擎盖下工作的? 非常感谢提前!
答案 0 :(得分:17)
这是个好问题。许多优秀的质量保证自动化专家都对此感到不满。
这是每个driver.findElement(...)
上的特殊隐藏自动等待。
如果在页面DOM结构中找不到元素,则原始webdriver(js,python,java)会抛出NoSuchElementException。无论您使用何种定位器,这种等待都将在每个driver.findElement
之前完成。当隐式等待超时时,将在findElement
函数之外抛出NoSuchElementException。
启用隐式等待
默认情况下,隐式等待超时设置为0
。 browser.manage().timeouts().implicitlyWait(3000)
使webdriver自动尝试/捕获此异常,并重试找到此元素。如果传递了3秒(超时),并且DOM中仍然没有元素 - 那么只有你得到NoSuchElementException。
什么时候好:
您的页面修改DOM结构(网站的99.999%),某些元素仍未在DOM中,但在1-3秒内显示。要不进行显式等待,并减少代码量 - 您可以尝试设置隐式等待超时。
什么时候不好:
您想测试DOM中不存在该元素。在每次.findElement
调用之前都会添加这种等待,所以当您尝试断言时:
expect($('NON-EXIST-ELEMENT').isPresent()).toBeFalsy()
您的implicitWait
仍然在这里工作。首先,你将等待3秒钟才能出现元素,然后抛出异常,并被isPresent()函数捕获,在这种情况下将返回false(我们实际断言的内容)。所以你等了3秒钟!设置implicitWait(0)
然后在断言元素不存在(这可能真的很烦人)之后将其设置回来是有意义的。
<强>结论强> 当你理解它是如何工作的时候,隐含的等待是好的。我建议不要将隐式等待设置超过1-5秒(您应该为每个网站定义自己的值)。此外,如果您计划断言许多不存在的元素 - 将隐式等待重置为0,然后将其重新设置。
这种等待你应该自己调用,但它比隐式等待更灵活。在protractorjs中,当您需要等待某事时,您必须致电browser.wait()
。它接受谓词函数(只返回true / false的函数,没有例外)。 Webdriver将轮询此函数,直到超时发生(您将其指定为第二个参数)。您还可以指定要作为第三个参数抛出的错误消息。
显然,在Web自动化中,您大多数时间都在等待一些元素条件。为此,人们创建了谓词函数的集合。此函数调用ExpectedConditions,并将为传递给它们的元素返回true / false。
browser.wait(ExpectedConditions.visibilityOf($('NON-EXISTING-ELEMENT')), 3000, 'error message')
好的时候: 当你必须等待你的元素的一些棘手的条件。您可以轻松定义要等待的自己的条件,指定自定义超时等。 在使用可能尚未准备好的元素进行操作之前使用。
什么时候不好:
当您尝试通过组合browser.sleep()
,隐式等待和显式等待来帮助您时。默认情况下,browser.sleep()
很糟糕,在99%的情况下,您可以使用提供的条件将其替换为browser.wait()
,或者编写您自己的条件。
当您拥有隐式等待设置并尝试调用显式等待时,会发生更多有趣的事情。
想像:
browser.manage().timeouts().implicitlyWait(10000)
browser.wait(EC.stalenessOf($('NON-EXIST-ELEMENT')), 5000) //waiting for 5 seconds for element to disappear
这里发生了什么:
等待函数调用元素的stalenessOf()
函数。在其中,driver.findElement()
被召唤。隐式等待不要让此函数立即抛出错误,并将网页池化10秒直到发生隐式等待超时,并且我们得到NoSuchElementException。发生异常,执行返回等待功能,已经过了10秒!等待以TimeOutException终止,因为它仅安排了5秒钟。我们的等待时间比预期的要长得多。
另请注意,JS是异步的,并且由于事件循环而无法保证准确的等待时间。通常这会使等待不准确 - 5200毫秒而不是5000(例如)。这是完全不同的故事:)
隐式超时 - 4000毫秒。
显式超时 - 5000毫秒。
presenceOf()
driver.findElement(By.xpath('//*[@name='qwer']'))
我希望这会有所帮助!
答案 1 :(得分:1)
这是一个很好的问题,当使用隐式和显式等待的组合时,这些不可预测的等待时间已被警告&amp;在Selenium documentation中说明。 browser.wait()
是明确的等待,您将其与implicit wait - browser.manage().timeouts().implicitlyWait()
等待使自动任务执行过了一定量 在继续下一步之前的时间。你应该选择使用 显式等待或隐式等待。
警告:不要混合隐式和显式等待。这样做可能会导致 不可预测的等待时间。例如,设置隐式等待10 秒和显式等待15秒,可能导致超时 20秒后发生。
答案 2 :(得分:0)
答案是:两个人等待并行。隐式等待轮询4秒并返回失败,此后显式等待仅等待4秒并且还有1个等待。这再次重新发出隐含的等待,并再次轮询4秒并再次失败。 8秒后(2次隐式等待尝试)5秒的显式等待也超时了,最后我们在浪费3个意外秒后得到错误。例如,在Implicit设置为8且Explicit设置为17的情况下,我们将等待8 * 3 = 24秒。请注意,脚本执行需要一些时间,因此如果下一次迭代很慢,则可能无法启动。