Create custom wait until condition in Python

◇◆丶佛笑我妖孽 提交于 2020-02-21 10:25:30

问题


I tried to create a function with custom wait condition in Python. However, I get an error:

TypeError: 'bool' object is not callable

def waittest(driver, locator, attr, value):
    element = driver.find_element_by_xpath(locator)
    if element.get_attribute(attr) == value:
        return element
    else:
        return False
wait = WebDriverWait(driver, 10)
element = wait.until(waittest(driver, '//div[@id="text"]', "myCSSClass", "false"))    

回答1:


WebDriverWait(driver, 10).until() accepts a callable object which will accept an instance of a webdriver (driver is our example) as an argument. The simplest custom wait, which expects to see 2 elements, will look like

WebDriverWait(driver, 10).until(
    lambda wd: len(wd.find_elements(By.XPATH, 'an xpath')) == 2
)

The waittest function has to be rewritten as:

class waittest:
    def __init__(self, locator, attr, value):
        self._locator = locator
        self._attribute = attr
        self._attribute_value = value

    def __call__(self, driver):
        element = driver.find_element_by_xpath(self._locator)
        if element.get_attribute(self._attribute) == self._attribute_value:
            return element
        else:
            return False

And then it can be used as

element = WebDriverWait(driver, 10).until(
    waittest('//div[@id="text"]', "myCSSClass", "false")
)



回答2:


what i really end up to do is using lamba self.wait.until(lambda x: waittest(driver, '//div[@id="text"]', "myCSSClass", "false"))




回答3:


It may not really answer question, I just want to save my custom wait function here :D

I don't like WebDriverWait() it need another import that not really easy to remember or type and it also used another function to select element.

Example:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC

WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME , 'myClass')))

here custom wait to use with default function

import time

def waitFor(maxSecond, runFunction, param):
    while maxSecond:
        try:
            return runFunction(param)
        except:
            time.sleep(0.5)
            maxSecond -= 0.5

Usage:

# wait 5 second
waitFor(5, driver.find_element_by_class_name, 'myClass')
# Or
link = waitFor(5, driver.find_element_by_class_name, 'myClass')
link.click()
# Or
link = waitFor(5,....)
if not link:
    print('Timeout, link not found')

and for reference

To find single elements

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

To find multiple elements (these methods will return a list):

  • find_elements_by_name
  • find_elements_by_xpath
  • find_elements_by_link_text
  • find_elements_by_partial_link_text
  • find_elements_by_tag_name
  • find_elements_by_class_name
  • find_elements_by_css_selector



回答4:


The wait.until(..) function from selenium expects a function that it can call. However, you are, effectively, giving it a boolean.

element = wait.until(waittest(driver, '//div[@id="text"]', "myCSSClass", "false"))

Can be rewritten as:

value = waittest(driver, '//div[@id="text"]', "myCSSClass", "false")
element = wait.until(value)

Which makes this more clear - waittest returns a boolean, and wait.until(..) tries to call it as a function - hence 'bool' object is not callable.

You need to have your custom condition return a function that selenium can call to check if it's true yet. You can do this by defining a function inside your function:

def waittest(locator, attr, value):
    def check_condition(driver):
        element = driver.find_element_by_xpath(locator)
        if element.get_attribute(attr) == value:
            return element
        else:
            return False
    return check_condition


来源:https://stackoverflow.com/questions/47420957/create-custom-wait-until-condition-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!