+3

Tìm hiểu về câu lệnh “Wait” trong Selenium WebDriver

Bài viết này mình sẽ giới thiệu với các bạn một câu lệnh rất hay sử dụng trong Selenium Webdriver, đó là câu lệnh Wait. Đối với người đã từng làm việc với Selenium Webdriver thì câu lệnh này không có gì là lạ lẫm nữa, nhưng mình cũng chắc là nhiều bạn cũng chưa hiểu rõ về câu lệnh này để có thể sử dụng một cách tốt nhất trong dự án của mình. Mình đặt ra vấn đề như thế này, một ngày nọ khi bạn đang implement một testcase, khi excute testcase này thì bạn nhận được một cục lỗi đại khái thế này “NoSuchElementExceptions”. Mình tin chắc là nhiều bạn mới bắt đầu làm với selenium webdriver sẽ lao đầu vào google, hoặc debug các kiểu để xem mình đang bị cái lỗi quái gì vậy, bởi vì hồi xưa mình cũng đã từng như thế.

Vậy “NoSuchElementExceptions” là lỗi gì? Đây là một exception được thằng Webdriver nó quăng ra từ 2 câu lệnh này WedDriver.findElement(By by) và WedElement.findElement(By by). Có nghĩa là khi bạn sử dụng 2 câu lệnh này để tìm kiếm 1 phần tử element ở trên page, nhưng vì một lí do nào đó mà nó không tìm được đúng đối tượng phần tử cần tìm, thì nó sẽ quăng ra cái lỗi ngớ ngẩn này.

Vậy nguyên nhân tại sao mà 2 câu lệnh trên lại không tìm đúng được phần tử cần tìm trên page? Theo mình có 2 nguyên nhân chính:

  • Nguyên nhân chủ quan đơn giản là do bạn code lỗi, khi bạn find một element nó không tồn tại trên page thì nó quăng cái lỗi này ra là đúng rồi!
  • Nguyên nhân khách quan còn lại là do khi mà bạn find element trên page thì đối tượng element cần tìm của bạn vẫn chưa được load xong ở trong DOM. Vì vậy khi selenium thực hiện câu lệnh driver.findElement() thì nó sẽ không tìm kiếm được đối tượng element này, vì vậy sẽ quăng ra exception như ở trên. Ví dụ:
 WebDriver driver = new FirefoxDriver();
 driver.get("http://ngocvudoan8292.com");
 WebElement loginButton = driver.findElement(By.id("loginbutton"));

Như ví dụ này thì trong khi Page đang thực hiện việc load resource về để render thì Selenium đã thực hiện câu lệnh driver.findElement(By.id("loginbutton")); này rồi; lúc đó thì thẻ <input type=’button’ id=’lgnbutton’ name=’Login’> vì một lí do nào đó mà vẫn chưa được load trong DOM, nên câu lệnh driver.findElement(By.id("loginbutton")); sẽ không bắt được element này, dẫn đến việc sẽ quăng ra exception như trên.

Để giải quyết vấn đề này, Selenium Webdriver hỗ trợ cho ta một tập các câu lệnh Wait để có thể bắt Webdriver đợi trong một khoản thời gian nhất định cho đến khi Page có thể load xong resource thì mới thực thi câu lệnh findElement, tránh tình trạng là sẽ không tìm được đối tượng element mong muốn. Dưới đây mình xin giới thiệu một số câu lệnh Wait trong Selenium WebDriver:

Implicitly Wait: Cú pháp:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Câu lệnh này sẽ bảo Selenium đợi trong một khoản thời gian nhất định trước khi quăng ra lỗi “NoSuchElementExceptions” rằng không thể tìm thấy phần tử trên page.

Ví dụ:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://ngocvudoan8292.com");
WebElement loginButton = driver.findElement(By.id("loginbutton"));

Câu lệnh Wait này luôn được đặt trước câu lệnh mở trình duyệt. Như ví dụ trên thì khi chạy câu lệnh driver.findElenment(By.id(“loginbutton”)); selenium sẽ chờ trong khoản 10s để tìm kiếm element có id='loginbutton', và sau 10s nếu vẫn kiếm không ra thì nó mới quăng ra thông báo lỗi “NoSuchElementExceptions ”. Trong khoản thời gian 10s, ví dụ đến giây thứ 5 đã kiếm ra được element mong muốn, thì selenium sẽ tự động bỏ qua 5s chờ còn lại và thực hiện tiếp câu lệnh tiếp theo. Đó là cái hay của Implicitly Wait.

FluentWait: Cú pháp:

Wait wait = new FluentWait(driver).withTimeout(30, SECONDS).pollingEvery(5, SECONDS).ignoring(NoSuchElementException.class);

Trong đó: withTimeout(30, SECONDS) : define ra thời gian chờ tối đa cho việc chờ một element được xuất hiện trong DOM. pollingEvery(5, SECONDS) : cứ mỗi 5s thì nó sẽ lại check lại việc element này đã xuất hiện trong DOM hay chưa. ignoring(NoSuchElementException.class): cho phép bỏ qua việc Selenium quăng ra một exception nào đó. Ở đây là exception NoSuchElementException. Ví dụ:

Wait wait = new FluentWait(driver).withTimeout(30, SECONDS).pollingEvery(5, SECONDS).ignoring(NoSuchElementException.class);
WebElement loginButton = wait.until(ExpectedConditions.visibilityOf(By.id("loginbutton"))); 

Như ví dụ trên, thì selenium sẽ set thời gian tối đa để thực hiện việc chờ element có id='loginbutton' xuất hiện trong DOM là 30s. Cứ mỗi 5 giây sẽ check việc element này đã xuất hiện trong DOM hay chưa. Và sau 30s nếu element này vẫn không xuất hiện trong DOM thì Selenium vẫn sẽ không quăng ra exception.

Sleep Command: Cú pháp:

thread.Sleep();

Đây là một câu lệnh mình khuyên các bạn nên hạn chế dùng. Trong trường hợp không thể sử dụng 2 câu lệnh Wait ở trên thì mới nên dùng đến câu lệnh này. Bởi vì đối với câu lệnh thread.Sleep() nó sẽ bắt Selenium đợi hết khoản thời gian mà bạn set để có thể thực hiện được câu lệnh tiếp theo.

Ví dụ:

WebDriver driver = new FirefoxDriver();
driver.get("http://ngocvudoan8292.com");
thread.sleep(10000); 
WebElement loginButton = driver.findElement(By.id("loginbutton"));

Ở ví dụ này, sau khi câu lệnh driver.get("http://ngocvudoan8292.com"); được thực hiện, thì đối với Implicitly Wait ở trên thì không cần đợi hết cả 10s, mà chỉ cần bất cứ lúc nào element xuất hiện trên DOM thì nó sẽ bỏ qua khoảng thời gian chờ còn lại và thực hiện câu lệnh tiếp theo, trong khi thread.sleep() bắt bạn phải đợi hết cả 10s thì mới cho thực hiện câu lệnh kế tiếp. Từ đó ta cũng thấy được sự bất lợi của việc sử dụng thread.sleep() nó khiến ta phải đợi một cách bị động, ảnh hưởng đến performance trong việc excute testcase.

Ở trên mình đã giới thiệu cho bạn 3 câu lệnh Wait rất hay sử dụng trong dự án Automation. Đối với mình thì mình cảm thấy nên vận dụng những câu lệnh này một cách linh hoạt, tùy thời điểm và tùy điều kiện của testcase thì sẽ đạt được kết quả tốt nhất. Sẽ vẫn còn rất nhiều cách để “Wait” trong selenium, các bạn có thể tìm hiểu thêm trên các blog công nghệ. Hy vọng bài này sẽ giúp các bạn hiểu hơn về Wait command trong Selenium.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.