使用页面对象模型在Python Selenium中显式等待

时间:2022-09-24 23:41:53

My explicit wait isn't waiting until the element is present. It literally waits the amount of seconds I declared and then the tests still fails. If I place a implicit wait in the exact same place the test passes. From what I'm reading, it's best practise to avoid implicit waits as much as possible. Am I doing something wrong?

我的显式等待不会等到元素存在。它确实等待我声明的秒数,然后测试仍然失败。如果我在一个完全相同的位置放置一个隐式等待,测试就会通过。从我正在阅读的内容来看,尽可能避免隐式等待是最好的做法。难道我做错了什么?

I have made a method in the base_page like so:

我在base_page中创建了一个方法,如下所示:

def _wait_for_is_displayed(self, locator, timeout):
        try:
            wait = WebDriverWait(self.driver, timeout)
            wait.until(expected_conditions.visibility_of_element_located((locator["by"], locator["value"])))
        except TimeoutException:
            return False
        return True

then i call the _wait_for_is_displayed method in a page object like so, but fails:

然后我在页面对象中调用_wait_for_is_displayed方法,但是失败了:

 def relatie_page_present(self):
     self._wait_for_is_displayed(self._open_actieve_polissen_tab, 10)

 def relatie_page_(self):
     self._click(self._open_relatie_details)
     self.relatie_page_present()

The error I get is:

我得到的错误是:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"td.first > a"}

This passes:

 def relatie_page_present(self):
        self.driver.implicitly_wait(10)

def relatie_page_(self):
    self._click(self._open_relatie_details)
    self.relatie_page_present()

Lastly in my test suite i call the relatie_page_present and relatie_page_ methods.

最后,在我的测试套件中,我调用了relatie_page_present和relatie_page_方法。

3 个解决方案

#1


0  

To clarify how implicit wait works, it is set one time on the driver and then is applied for the life of the driver instance. So calling self.driver.implicitly_wait(10) doesn't actually wait at that moment... it just sets the driver to wait from that point on when an element is located. I think this confuses a lot of people because I see it quite a bit.

为了阐明隐式等待是如何工作的,它在驱动程序上设置了一次,然后应用于驱动程序实例的生命周期。因此,调用self.driver.implicitly_wait(10)实际上并不会在那一刻等待...它只是将驱动程序设置为等待元素定位时的那个点。我认为这让很多人感到困惑,因为我看到了很多。

Anyway, if I were you, I would use a function like the below that waits for the element to be clickable and then clicks it. You can call it any time you need to potentially wait for an element to be clicked.

无论如何,如果我是你,我会使用类似下面的函数,等待元素可点击,然后点击它。您可以在需要等待单击元素时随时调用它。

def _wait_and_click(self, locator, timeout):
    try:
        wait = WebDriverWait(self.driver, timeout)
        wait.until(expected_conditions.element_to_be_clickable((locator["by"], locator["value"]))).click()
    except TimeoutException:
        return False
    return True

#2


0  

Moving forward as you are trying to invoke click() so instead of using expected_conditions as visibility_of_element_located() you should have been using element_to_be_clickable() as follows :

当您尝试调用click()而不是将expected_conditions用作visibility_of_element_located()时,您应该继续使用element_to_be_clickable(),如下所示:

try:
    wait = WebDriverWait(self.driver, timeout)
    wait.until(expected_conditions.element_to_be_clickable((locator["by"], locator["value"])))
  • Element is Clickable - WebElement is Displayed and Enabled.
  • 元素是可单击的 - WebElement已显示并已启用。

Avoid mixing up implicit wait and explicit wait as the documentation clearly mentions :

避免混淆隐式等待和显式等待,因为文档清楚地提到:

WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

警告:不要混合隐式和显式等待。这样做会导致不可预测的等待时间。例如,设置10秒的隐式等待和15秒的显式等待可能导致20秒后发生超时。

#3


0  

Implicit wait is to set the timeout for find element API, like find_element_by_xxx and find_elements_by_xxx. Its default value is 10 seconds.

隐式等待是为find元素API设置超时,如find_element_by_xxx和find_elements_by_xxx。其默认值为10秒。

It's a global setting. Once you change the implicit wait, all code place where call find element API will take the same time out value.

这是一个全球性的环境。一旦更改了隐式等待,所有调用find元素API的代码将占用相同的超时值。

If you feel most page/response of your website slow, you can change it with increased time out value until meet next implicit wait.

如果您觉得网站的大多数页面/响应都很慢,您可以使用增加的超时值来更改它,直到遇到下一次隐式等待。

But it's not equivalent to say the implicit wait time out value is more large more better.

但这并不等于说隐含的等待超时值越大越好。

Assume your website UI has huge changes or many page fail to open/load, if the implicit wait time out value large, it will increase the durtion time of whole running. Because every time of find element have to wait that large number seconds then throw timeout exception.

假设您的网站UI发生巨大变化或许多页面无法打开/加载,如果隐式等待超时值大,则会增加整个运行的持续时间。因为每次查找元素都必须等待那么大的秒数然后抛出超时异常。

Explicit wait only impact the code which use it, it's global impact.

显式等待仅影响使用它的代码,它具有全局影响。

I see you set explicit wait time out is 10 seconds, it's no longer than the default value of Implicit wait.

我看到你设置明确的等待时间是10秒,它不会超过隐式等待的默认值。

In general, Explicit wait should longer than the Implicit wait, otherwise no need to use it, using find element API can archive same effect.

一般来说,显式等待应该比Implicit等待更长,否则不需要使用它,使用find element API可以存档相同的效果。

#1


0  

To clarify how implicit wait works, it is set one time on the driver and then is applied for the life of the driver instance. So calling self.driver.implicitly_wait(10) doesn't actually wait at that moment... it just sets the driver to wait from that point on when an element is located. I think this confuses a lot of people because I see it quite a bit.

为了阐明隐式等待是如何工作的,它在驱动程序上设置了一次,然后应用于驱动程序实例的生命周期。因此,调用self.driver.implicitly_wait(10)实际上并不会在那一刻等待...它只是将驱动程序设置为等待元素定位时的那个点。我认为这让很多人感到困惑,因为我看到了很多。

Anyway, if I were you, I would use a function like the below that waits for the element to be clickable and then clicks it. You can call it any time you need to potentially wait for an element to be clicked.

无论如何,如果我是你,我会使用类似下面的函数,等待元素可点击,然后点击它。您可以在需要等待单击元素时随时调用它。

def _wait_and_click(self, locator, timeout):
    try:
        wait = WebDriverWait(self.driver, timeout)
        wait.until(expected_conditions.element_to_be_clickable((locator["by"], locator["value"]))).click()
    except TimeoutException:
        return False
    return True

#2


0  

Moving forward as you are trying to invoke click() so instead of using expected_conditions as visibility_of_element_located() you should have been using element_to_be_clickable() as follows :

当您尝试调用click()而不是将expected_conditions用作visibility_of_element_located()时,您应该继续使用element_to_be_clickable(),如下所示:

try:
    wait = WebDriverWait(self.driver, timeout)
    wait.until(expected_conditions.element_to_be_clickable((locator["by"], locator["value"])))
  • Element is Clickable - WebElement is Displayed and Enabled.
  • 元素是可单击的 - WebElement已显示并已启用。

Avoid mixing up implicit wait and explicit wait as the documentation clearly mentions :

避免混淆隐式等待和显式等待,因为文档清楚地提到:

WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

警告:不要混合隐式和显式等待。这样做会导致不可预测的等待时间。例如,设置10秒的隐式等待和15秒的显式等待可能导致20秒后发生超时。

#3


0  

Implicit wait is to set the timeout for find element API, like find_element_by_xxx and find_elements_by_xxx. Its default value is 10 seconds.

隐式等待是为find元素API设置超时,如find_element_by_xxx和find_elements_by_xxx。其默认值为10秒。

It's a global setting. Once you change the implicit wait, all code place where call find element API will take the same time out value.

这是一个全球性的环境。一旦更改了隐式等待,所有调用find元素API的代码将占用相同的超时值。

If you feel most page/response of your website slow, you can change it with increased time out value until meet next implicit wait.

如果您觉得网站的大多数页面/响应都很慢,您可以使用增加的超时值来更改它,直到遇到下一次隐式等待。

But it's not equivalent to say the implicit wait time out value is more large more better.

但这并不等于说隐含的等待超时值越大越好。

Assume your website UI has huge changes or many page fail to open/load, if the implicit wait time out value large, it will increase the durtion time of whole running. Because every time of find element have to wait that large number seconds then throw timeout exception.

假设您的网站UI发生巨大变化或许多页面无法打开/加载,如果隐式等待超时值大,则会增加整个运行的持续时间。因为每次查找元素都必须等待那么大的秒数然后抛出超时异常。

Explicit wait only impact the code which use it, it's global impact.

显式等待仅影响使用它的代码,它具有全局影响。

I see you set explicit wait time out is 10 seconds, it's no longer than the default value of Implicit wait.

我看到你设置明确的等待时间是10秒,它不会超过隐式等待的默认值。

In general, Explicit wait should longer than the Implicit wait, otherwise no need to use it, using find element API can archive same effect.

一般来说,显式等待应该比Implicit等待更长,否则不需要使用它,使用find element API可以存档相同的效果。