Protractor的隐式等待如何与显式等待交互? [英] How does implicit wait of Protractor interact with explicit wait?

查看:118
本文介绍了Protractor的隐式等待如何与显式等待交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当隐式等待小于显式时会发生误解:

The misunderstanding happens when implicit wait is less than explicit:

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秒。它是如何在引擎盖下工作的?
非常感谢提前!

Overall time: 8.613 seconds. Set implicitlyWait a second lower: 3000 and result is 6.865 seconds. How does it work under the hood? Big thanks in advance!

推荐答案

这是个好问题。许多优秀的QA自动化家伙都为此打破了主题。

Thats nice question. A lot of good QA automation guys broke their heads with this.

这是特殊隐藏自动等待,在每个 driver.findElement(...)上。
原始webdriver(js,python,java)如果在页面DOM结构中找不到元素,则抛出NoSuchElementException。无论你使用什么类型的定位器,这种等待都将在每个 driver.findElement 之前完成。当隐式等待超时时,NoSuchElementException将抛出 findElement 函数。

This is special hidden automatic wait, on each driver.findElement(...). Original webdriver (js, python, java) throws NoSuchElementException if element cannot be found in page DOM structure. This kind of wait will be done before EVERY driver.findElement, no matter what kind of locator do you use. When implicit wait timed out, NoSuchElementException will be thrown outside findElement function.

启用隐式等待

默认情况下,隐式等待超时设置为 0 browser.manage()。timeouts()。implicitlyWait(3000)使webdriver自动尝试/捕获此异常,并重试找到此元素。如果3秒(超时)通过,并且元素仍然不存在于DOM中 - 只有那时你得到NoSuchElementException。

By default implicit wait timeout is set to 0. browser.manage().timeouts().implicitlyWait(3000) makes webdriver automatically try/catch this exception, and retry to find this element. If 3 seconds (timeout) passed, and element is still not present in DOM - only then you are getting NoSuchElementException.

什么时候好:

您的页面修改DOM结构(网站的99.999%),一些元素仍然不在DOM中,但在1-3秒内出现。要不进行明确的等待,并减少代码量 - 您可以尝试设置隐式等待超时。

Your page modify DOM structure (99.999% of website) and some elements still not in the DOM, but appear within 1-3 seconds. To not make explicit waits, and reduce amount of code - you can try to set implicit wait timeout.

当它不好时:
您想测试DOM中不存在该元素。在每个 .findElement 调用之前添加这种等待,所以当你试图这样断言时:

When it is bad: You want to test that element is not present in the DOM. This kind of wait is added before every .findElement call, so when you are trying to assert like this:

expect($('NON-EXIST-ELEMENT')。isPresent())。toBeFalsy()

你的 implicitWait 仍然在这里工作。首先,你将等待3秒钟才能出现元素,然后抛出异常,并被isPresent()函数捕获,在这种情况下将返回false(我们实际断言的内容)。所以你等了3秒钟!设置 implicitWait(0)是有意义的,然后在断言元素不存在之后将其设置回来(这可能真的很烦人)。

Your implicitWait still working here. First you will wait for 3 seconds to element to be present, then exception will be thrown, and caught by isPresent() function, that will return false in this case (what we actually asserting). So you are waiting for 3 extra seconds! It makes sense to set implicitWait(0) and then set it back after asserting element is not present (which might be really annoying).

结论
当您了解它是如何工作时,隐式等待是好的。我建议不要将隐式等待设置超过1-5秒(您应该为每个网站定义自己的值)。此外,如果您计划断言许多不存在的元素 - 将隐式等待重置为0,然后将其重新设置。

Conclusion Implicit waits are good, when you understand how it is works. I recommend to not set implicit wait more than 1-5 seconds (you should define own value for each website). Also if you plan to assert lot of not-present elements - reset implicit wait to 0, and then set it back.

这种等待你应该自己调用,但它比隐含更灵活等待的时间。在protractorjs中,当你需要等待某事时,你必须调用 browser.wait()。它接受谓词函数(只返回true / false的函数,没有例外)。 Webdriver将轮询此函数,直到超时发生(您将其指定为第二个参数)。您还可以指定要作为第三个参数抛出的错误消息。

This kind of waiting that you should call by yourself, but it much more flexible than implicit waits. In protractorjs, when you need to wait for something, you must call browser.wait(). It accepts predicate function (function that will return only true/false, no exceptions). Webdriver will poll this function until timeout occurs (you specify it as second param). Also you can specify error message that you want to throw as third parameter.

显然,在Web自动化中,您大多数时间都在等待一些元素条件。为此,人们创建了谓词函数的集合。此函数调用ExpectedConditions,并将为传递给它们的元素返回true / false。

Obviously, that in web automation you wait for some element conditions most of the time. For this guys have created collection of predicate functions. This functions calls ExpectedConditions, and will return true/false for element that was passed to them.

browser.wait(ExpectedConditions.visibilityOf($( 'NON-EXISTING-ELEMENT')),3000,'错误信息')

什么时候好:
当你必须等待元素的一些棘手条件时。您可以轻松定义要等待的自己的条件,指定自定义超时等。
在使用可能尚未准备好的元素进行操作之前使用。

When it is good: When you have to wait for some tricky conditions of your elements. You can easily define own conditions that you want to wait, specify custom timeout and so on. Use before manipulating with elements that might not be ready yet.

当它不好时:
当你尝试通过组合 browser.sleep(),隐式等待和显式等待来帮助您。 browser.sleep()默认情况下不好,在99%的情况下你可以用 browser.wait()提供条件,或写自己的条件。

When it is bad: When you try to help you by combining browser.sleep(), implicit waits and explicit waits together. browser.sleep() is bad by default, in 99% of cases you can replace it with browser.wait() with provided conditions, or write your own condition.

当你有隐式等待设置,而你试图调用显式等待时,会发生更多的乐趣。
想象一下:
browser.manage()。timeouts()。implicitlyWait(10000)
browser.wait (EC.stalenessOf($('NON-EXIST-ELEMENT')),5000)//等待5秒钟元素消失

Much more fun happens when you have your implicit wait set, and you trying to call explicit wait. Imagine: 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秒钟。我们得到的错误等待时间比预期的要长得多。

What happens here: Wait function calls stalenessOf() function for your element. Inside it, driver.findElement() got called. Implicit wait don't let this function to throw error immediately, and pools webpage for 10 seconds until implicit wait timeout happens, and we are getting NoSuchElementException. Exception happens, and execution returns to wait function, 10 seconds are passed already! Wait is terminated with TimeOutException, because it was scheduled only for 5 seconds. We are getting error with wait time much longer that expected.

还要记住JS是异步的,并且由于事件循环而无法保证准确的等待时间。通常这会使等待不准确 - 5200毫秒而不是5000(例如)。这是完全不同的故事:)

Also keep in mind that JS is async, and cannot guarantee exact wait time because of Event Loop. Usually this makes waiting not exact - 5200 ms instead 5000 (as example). This is absolutely different story :)

隐式超时 - 4000毫秒。

implicit timeout - 4000 milliseconds.

显式超时 - 5000毫秒。

explicit timeout - 5000 milliseconds.


  1. 等等。第一次调用谓词函数 - presenceOf()

  2. 内部谓词调用原始webdriverjs函数 - driver.findElement( By.xpath('// * [@ name ='qwer']'))

  3. 由于设置了隐式等待,我们在抛出之前等待它错误。

  4. 传递4000毫秒的隐式元素等待。只是现在我们将错误返回到谓词函数。

  5. 谓词函数捕获错误,而返回false

  6. 因为我们在超时之前仍然有1000毫秒显式等待 - 再次调用谓词函数。

  7. 隐式等待再次开始。 4000毫秒之后 - 将错误抛回谓词函数

  8. 谓词返回false

  9. 等待函数变为false,我们的显式等待时间已过时 - 在理想情况 - 它大概是8000毫秒,但也要注意异步调用,所以实时会更多

  10. 等待抛出错误 - jasminejs捕获错误,并且测试失败

  1. Wait started. First time calling predicate function - presenceOf()
  2. Internally predicate calls original webdriverjs function - driver.findElement(By.xpath('//*[@name='qwer']'))
  3. Since implicit wait is set, we are waiting for it before throw error.
  4. 4000 milliseconds of implicit element waiting passed. Only now we are returning error to predicate function.
  5. Predicate function catch error, and returns false instead
  6. Since we still have 1000 milliseconds before timeout of explicit wait - calling predicate function again.
  7. Implicit wait started again. 4000 milliseconds later - throwing error back to predicate function
  8. Predicate returns false
  9. Wait function got false, and our explicit wait is out of time - in ideal case - it would be about 8000 milliseconds, but also be aware about async calls, so real time would be more
  10. Wait throws error - jasminejs catch error, and fails test

我希望这会有所帮助!

这篇关于Protractor的隐式等待如何与显式等待交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆