1. Flaky test là gì và vì sao nó chết người
Một test flaky là test có lúc xanh có lúc đỏ trên cùng một đoạn code không đổi. Trong hệ thống lõi của một ngân hàng số, nơi mỗi lần release chạm tới giao dịch tiền thật, một bộ test hay đỏ ngẫu nhiên còn nguy hiểm hơn không có test: nó khiến đội mất niềm tin, bắt đầu bấm chạy lại cho tới khi xanh, và cuối cùng vô hiệu hoá luôn cả những lần đỏ thật sự là bug. Nguyên nhân số một của flaky trong Selenium là đồng bộ hoá sai: test chạy nhanh hơn tốc độ ứng dụng cập nhật DOM. Bài này đào sâu ba loại wait, ExpectedConditions, điều kiện tuỳ biến, stale element, race condition và chiến lược retry để đưa tỉ lệ flaky về gần không.
2. Implicit wait: tiện nhưng nhiều bẫy
Implicit wait được đặt một lần cho cả driver bằng driver.implicitly_wait(10). Sau đó mọi lệnh findElement sẽ tự poll DOM tối đa 10 giây trước khi ném NoSuchElementException. Nghe rất tiện, nhưng nó có ba nhược điểm nghiêm trọng. Thứ nhất, nó chỉ chờ phần tử có mặt trong DOM, không chờ phần tử hiển thị hay có thể click, nên bạn vẫn dính ElementNotInteractableException. Thứ hai, nó áp lên mọi lời gọi kể cả những chỗ bạn cố ý muốn kiểm tra phần tử KHÔNG tồn tại, làm test kiểm tra vắng mặt chậm chạp một cách vô lý. Thứ ba, trộn nó với explicit wait gây cộng dồn thời gian khó lường. Nhiều đội trưởng thành chọn tắt hẳn implicit wait và chỉ dùng explicit.
# Đặt implicit wait (nếu dùng) — CHỈ đặt một lần, đừng trộn explicit
driver.implicitly_wait(0) # nhiều đội đặt 0 để tắt hẳn, dùng explicit thay thế
# Hệ quả: kiểm tra một phần tử vắng mặt sẽ RẤT chậm nếu implicit > 0
elements = driver.find_elements(By.CSS_SELECTOR, ".error") # trả [] ngay nếu implicit=0
assert len(elements) == 0, "Không được có lỗi hiển thị"3. Explicit wait và ExpectedConditions
Explicit wait là công cụ chủ lực. Bạn tạo một WebDriverWait với timeout và chu kỳ poll, rồi truyền vào một điều kiện. Selenium cung cấp sẵn một bộ ExpectedConditions bao trùm hầu hết nhu cầu: presence_of_element_located chờ phần tử vào DOM, visibility_of_element_located chờ nó hiển thị, element_to_be_clickable chờ nó vừa hiển thị vừa bật, text_to_be_present_in_element chờ nội dung, staleness_of chờ một phần tử cũ biến mất, và alert_is_present chờ hộp thoại. Chọn đúng điều kiện cho đúng ý định là mấu chốt: nếu bạn định click thì chờ element_to_be_clickable chứ đừng chỉ chờ presence, vì phần tử có trong DOM chưa chắc đã bấm được.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 15, poll_frequency=0.5)
wait.until(EC.presence_of_element_located((By.ID, "app"))) # có trong DOM
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".modal"))) # hiển thị
btn = wait.until(EC.element_to_be_clickable((By.ID, "pay"))) # bấm được
btn.click()
wait.until(EC.text_to_be_present_in_element(
(By.CSS_SELECTOR, ".status"), "Thành công")) # có nội dung
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!