Hướng dẫn expected_conditions selenium python - Con trăn selen được mong đợi

Sao cùng 1 dòng code nhưng có lúc chạy nó click được có lúc nó lại đứng yên vậy?

Test case này lúc nãy tôi vừa mới chạy pass xong mà, sao chưa đầy 1 phút chạy lại thì fail rồi???

Tôi cá rằng nếu bạn đã từng viết automation thì sẽ không ít lần bạn đã gặp phải những trường hợp trên, nếu muốn test manual 1 trang web buộc chúng ta phải đợi cho page đó load xong, thì với automation test muốn chạy được phải để cho element được enable, tức là nó phải ở trong trạng thái sẵn sàng để chương trình có thể thực hiện action lên nó.

Vậy làm sao để chương trình test của chúng ta hiểu được element này đã sẵn sàng hay chưa?

Trong bài này tôi sẽ hướng dẫn các bạn sử dụng những câu lệnh Wait trong selenium để giải quyết bài toán trên nhé!

1. ElementToBeClickable

Đối với những element có thể click, ví dụ như button, link, dropdown,.... thì chúng ta hãy sử dụng câu lệnh sau:

WebDriverWait wait = new WebDriverWait(driver,20); //20 seconds
wait.until(ExpectedConditions.elementToBeClickable(element));
driver.findElement(element).click(); 

Lúc này chương trình sẽ chờ tối đa 20 giây để đợi element enable , sau đó action click mới được thực hiện. Nếu chỉ sau 3s element đã enable thì sau 3s thao tác click sẽ được thực hiện

2. VisibilityOf

Đối với những element chỉ display, chỉ cần chờ nó hiển thị, ví dụ như: text, label, image,.. thì hãy sử dụng lệnh sau:

WebDriverWait wait = new WebDriverWait(driver, 20); //20 seconds
wait.until(ExpectedConditions.visibilityOf(element));

Chương trình sẽ đợi tối đa 20s cho tới khi element được hiển thị

3. VisibilityOfAllElements

Tương tự với visibilityOf thì visibilityOfAllElements được dùng để wait cho 1 list element, lúc này giá trị element truyền vào phải là 1 listvisibilityOfAllElements được dùng để wait cho 1 list element, lúc này giá trị element truyền vào phải là 1 list

WebDriverWait wait = new WebDriverWait(driver, 20); //20 seconds
wait.until(ExpectedConditions.visibilityOfAllElements(listElement));

Chương trình sẽ đợi tối đa 20s cho tới khi toàn bộ list element được hiển thị

3. Sleep

Thực ra trong automation rất hạn chế dùng sleep, nó mang tính khá cố định

Thread.sleep(10000) //10000 milisecond
driver.findElement(element).click(); 

Nếu sử dụng câu lệnh trên thì chương trình sẽ cố định chờ 10s mới thực hiện action click, nếu sau 3s element đã được enable nhưng vẫn phải chờ tới 10s nó mới được click, việc này làm cho chương trình không được linh động nên hãy hạn chế sử dụng sleep một cách tối thiểu nhất.

Tuy nhiên automation nhiều lúc rất nhanh, đôi lúc sử dụng elementToBeClickable , visibilityOf ,... nhưng do chương trình chạy quá nhanh nó vẫn bị fail, buộc bạn phải kết hợp vừa sleep vừa elementToBeClickable để có thể tối ưu được cách sử dụng wait, hãy dùng sleep khoảng 500 milisecond ở phía trước lệnh visibilityOf thì sẽ làm cho chương trình ổn định hơn.elementToBeClickable , visibilityOf ,... nhưng do chương trình chạy quá nhanh nó vẫn bị fail, buộc bạn phải kết hợp vừa sleep vừa elementToBeClickable để có thể tối ưu được cách sử dụng wait, hãy dùng sleep khoảng 500 milisecond ở phía trước lệnh visibilityOf thì sẽ làm cho chương trình ổn định hơn.

Thread.sleep(500) 
WebDriverWait wait = new WebDriverWait(driver,20); //20 seconds
wait.until(ExpectedConditions.elementToBeClickable(element));
driver.findElement(element).click();

Ngày nay, hầu hết các ứng dụng web đang sử dụng các kỹ thuật AJAX. Khi một trang được tải bởi trình duyệt, các phần tử trong trang đó có thể tải ở các khoảng thời gian khác nhau. Điều này làm cho việc định vị các yếu tố khó khăn: nếu một phần tử chưa có trong DOM, hàm định vị sẽ tăng ngoại lệ phần tử. Sử dụng chờ đợi, chúng ta có thể giải quyết vấn đề này. Chờ đợi cung cấp một số sự chậm chạp giữa các hành động được thực hiện - chủ yếu là định vị một phần tử hoặc bất kỳ hoạt động nào khác với phần tử.

Selenium WebDriver cung cấp hai loại chờ đợi - ngầm & rõ ràng. Một sự chờ đợi rõ ràng làm cho WebDriver chờ đợi một điều kiện nhất định xảy ra trước khi tiến hành thực hiện. Một sự chờ đợi ngầm làm cho WebDriver thăm dò DOM trong một khoảng thời gian nhất định khi cố gắng xác định vị trí một phần tử.

5.1. Chờ đợi rõ ràng

Chờ đợi rõ ràng là một mã bạn xác định để chờ đợi một điều kiện nhất định xảy ra trước khi tiến hành thêm trong mã. Trường hợp cực đoan của điều này là thời gian.s ngủ (), đặt điều kiện ở một khoảng thời gian chính xác để chờ đợi. Có một số phương thức tiện lợi với điều kiện giúp bạn viết mã sẽ chỉ chờ đợi miễn là yêu cầu. WebDriverWait kết hợp với dự kiến ​​là một cách này có thể được thực hiện.

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

driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

Trong mã trên, Selenium sẽ chờ tối đa 10 giây cho một yếu tố phù hợp với các tiêu chí đã cho được tìm thấy. Nếu không có yếu tố nào được tìm thấy trong thời gian đó, thời gian chờ được ném. Theo mặc định, WebDriverWait gọi điều kiện dự kiến ​​cứ sau 500 mili giây cho đến khi nó trở lại thành công. Dự kiến ​​sẽ trả về true (boolean) trong trường hợp thành công hoặc không vô hiệu nếu nó không xác định được một phần tử.

Điều kiện mong đợi

Có một số điều kiện phổ biến thường được sử dụng khi tự động hóa các trình duyệt web. Được liệt kê dưới đây là tên của mỗi. Selenium Python Binding cung cấp một số phương thức tiện lợi để bạn không phải tự mình mã hóa một lớp dự kiến ​​hoặc tạo gói tiện ích của riêng bạn cho chúng.

  • Tiêu đề_is
  • title_contains
  • presence_of_element_located
  • visibility_of_element_located
  • visibility_of
  • presence_of_all_elements_located
  • text_to_be_present_in_element
  • text_to_be_present_in_element_value
  • frame_to_be_available_and_switch_to_it
  • invisibility_of_element_located
  • element_to_be_clickable
  • staleness_of
  • element_to_be_selected
  • element_located_to_be_selected
  • element_selection_state_to_be
  • Element_located_selection_state_to_be
  • alert_is_present

from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

Mô -đun dự kiến_conditions chứa một tập hợp các điều kiện được xác định trước để sử dụng với WebDriverWait.

Điều kiện chờ tùy chỉnh

Bạn cũng có thể tạo các điều kiện chờ tùy chỉnh khi không có phương thức tiện lợi nào trước đó phù hợp với yêu cầu của bạn.Một điều kiện chờ tùy chỉnh có thể được tạo bằng cách sử dụng một lớp với phương thức __call__ trả về sai khi điều kiện không khớp.

class element_has_css_class(object):
  """An expectation for checking that an element has a particular css class.

  locator - used to find the element
  returns the WebElement once it has the particular css class
  """
  def __init__(self, locator, css_class):
    self.locator = locator
    self.css_class = css_class

  def __call__(self, driver):
    element = driver.find_element(*self.locator)   # Finding the referenced element
    if self.css_class in element.get_attribute("class"):
        return element
    else:
        return False

# Wait until an element with id='myNewInput' has class 'myCSSClass'
wait = WebDriverWait(driver, 10)
element = wait.until(element_has_css_class((By.ID, 'myNewInput'), "myCSSClass"))

Ghi chú

Thư viện bỏ phiếu2

Bạn cũng có thể xem xét sử dụng thư viện Polling2 mà bạn cần cài đặt riêng.

5.2.Chờ đợi ngầm

Một sự chờ đợi ngầm cho WebDriver bỏ phiếu DOM trong một khoảng thời gian nhất định khi cố gắng tìm bất kỳ yếu tố (hoặc phần tử) nào không có sẵn ngay lập tức.Cài đặt mặc định là 0 (không).Sau khi được đặt, sự chờ đợi ngầm được đặt cho cuộc sống của đối tượng WebDriver.

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")