2013-05-09 25 views
13

Tôi đang sử dụng Selenium 2/WebDriver với các API Python, như sau:Điều kiện dự kiến ​​Selenium - có thể sử dụng 'hoặc'?

from selenium.webdriver.support import expected_conditions as EC 

# code that causes an ajax query to be run 

WebDriverWait(driver, 10).until(EC.presence_of_element_located(\ 
    (By.CSS_SELECTOR, "div.some_result"))); 

Tôi muốn đợi cho hai Kết quả là để được trả lại (div.some_result) hay một "Không tìm thấy" chuỗi . Điều đó có thể không? Loại:

WebDriverWait(driver, 10).until(\ 
    EC.presence_of_element_located(\ 
     (By.CSS_SELECTOR, "div.some_result")) \ 
    or 
    EC.presence_of_element_located(\ 
     (By.CSS_SELECTOR, "div.no_result")) \ 
); 

Tôi nhận ra tôi có thể làm điều này với một chọn CSS (div.no_result, div.some_result), nhưng là có một cách để làm điều đó bằng cách sử dụng Selenium dự kiến ​​điều kiện phương pháp?

+0

hãy xem http://stackoverflow.com/questions/7781792/selenium- này waitforelement, có thể giúp bạn .. –

+0

Lớp ExpectedConditions gọn gàng mọi thứ nhưng tôi đã học được rằng nó không phải là rất đáng tin cậy (ở dạng thuần túy) và bạn cần nắm bắt rõ ràng các điều kiện ngoại lệ liên quan đến việc sử dụng nó và đôi khi lặp lại thử lại trên thất bại. – djangofan

Trả lời

12

tôi đã làm nó như thế này:

class AnyEc: 
    """ Use with WebDriverWait to combine expected_conditions 
     in an OR. 
    """ 
    def __init__(self, *args): 
     self.ecs = args 
    def __call__(self, driver): 
     for fn in self.ecs: 
      try: 
       if fn(driver): return True 
      except: 
       pass 

Sau đó gọi nó như thế ...

from selenium.webdriver.support import expected_conditions as EC 
# ... 
WebDriverWait(driver, 10).until(AnyEc(
    EC.presence_of_element_located(
     (By.CSS_SELECTOR, "div.some_result")), 
    EC.presence_of_element_located(
     (By.CSS_SELECTOR, "div.no_result")))) 

Rõ ràng nó sẽ là tầm thường cũng để thực hiện một lớp AllEc tương tự như vậy.

Nb. khối try: là số lẻ. Tôi đã bối rối vì một số EC trở lại đúng/sai trong khi những người khác sẽ ném ngoại lệ cho Sai. Các ngoại lệ bị WebDriverWait bắt giữ để điều AnyEc của tôi tạo ra kết quả kỳ quặc vì kết quả đầu tiên ném ngoại lệ có nghĩa là AnyEc đã không tiến hành thử nghiệm tiếp theo.

-2

Cố gắng biểu hiện sử dụng lambda:

WebDriverWait(driver, 10).until(lambda a:
a.presence_of_element_located(By.CSS_SELECTOR, "div.some_result") OR a.presence_of_element_located(By.CSS_SELECTOR, "div.no_result"))

1

câu hỏi cổ nhưng,

xem xét như thế nào WedDriverWait công trình, trong một ví dụ độc lập từ selen:

def is_even(n): 
    return n % 2 == 0 

x = 10 

WebDriverWait(x, 5).until(is_even) 

chí này đợi tối đa 5 giây cho is_even(x) trở True

bây giờ, WebDriverWait(7, 5).until(is_even) sẽ mất 5 giây và họ nâng cao một TimeoutException

Hóa ra, bạn có thể trả lại bất kỳ giá trị không Falsy và nắm bắt nó:

def return_if_even(n): 
    if n % 2 == 0: 
     return n 
    else: 
     return False 

x = 10 
y = WebDriverWait(x, 5).until(return_if_even) 
print(y) # >> 10 

Bây giờ xem xét như thế nào phương pháp của EC hoạt động:

print(By.CSS_SELECTOR) # first note this is only a string 
>> 'css selector' 

cond = EC.presence_of_element_located(('css selector', 'div.some_result')) 
# this is only a function(*ish), and you can call it right away: 

cond(driver) 
# if element is in page, returns the element, raise an exception otherwise 

Có thể bạn sẽ muốn thử một số thứ e:

def presence_of_any_element_located(parent, *selectors): 
    ecs = [] 
    for selector in selectors: 
     ecs.append(
      EC.presence_of_element_located(('css selector', selector)) 
     ) 

    # Execute the 'EC' functions agains 'parent' 
    ecs = [ec(parent) for ec in ecs] 

    return any(ecs) 

này sẽ làm việc nếu EC.presence_of_element_located trở False khi selector không tìm thấy trong parent, nhưng nó đặt ra một ngoại lệ, một dễ hiểu workaround sẽ là:

def element_in_parent(parent, selector): 
    matches = parent.find_elements_by_css_selector(selector) 
    if len(matches) == 0: 
     return False 
    else: 
     return matches 

def any_element_in_parent(parent, *selectors): 
    for sel in selectors: 
     matches = element_in_parent(parent, selector) 
     # if there is a match, return right away 
     if matches: 
      return matches 
    # If list was exhausted 
    return False 

# let's try 
any_element_in_parent(driver, 'div.some_result', 'div.no_result') 
# if found in driver, will return matches, else, return False 

# For convenience, let's make a version wich takes a tuple containing the arguments: 
cond = lambda args: any_element_in_parent(*args) 
cond((driver, 'div.some_result', 'div.no_result')) 
# exactly same result as above 

# At last, wait up until 5 seconds for it 
WebDriverWait((driver, 'div.some_result', 'div.no_result'), 5).until(cond) 

Mục tiêu của tôi là để giải thích, artfulrobot đã đưa ra một đoạn trích để sử dụng chung các phương pháp thực tế EC, chỉ cần lưu ý rằng

class A(object): 
    def __init__(...): pass 
    def __call__(...): pass 

Chỉ là một cách linh hoạt hơn để xác định các hàm (thực tế, 'giống như chức năng', nhưng điều đó không liên quan trong ngữ cảnh này)

Các vấn đề liên quan