Selenium-Handle StaleElementReferenceException

Đây là exception khá "chuối" của selenium . Nó xảy ra tại bất kì dòng code nào , có thể liên tục và không liên tục. Vì thế việc tái hiện code và xử lý khiển người lập trình khá nhiều time. Chúng ta sẽ cùng làm rõ vấn đề này:
Đây là message tôi nhận được khi exception xẩy ra.

Element not found in the cache - perhaps the page has changed since it was looked up For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html Build info: version: '2.45.0', revision: '5017cb8', time: '2015-02-26 23:59:50' System info: host: 'b69945ec1416', ip: '172.17.0.8', os.name: 'Linux', os.arch: 'amd64', os.version: '3.13.0-48-generic', java.version: '1.8.0_20' Driver info: driver.version: unknown Command duration or timeout: 2.53 seconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html Build info: version: '2.46.0', revision: '61506a4624b13675f24581e453592342b7485d71', time: '2015-06-04 10:22:50' System info: host: 'b69945ec1416', ip: '172.17.0.8', os.name: 'Linux', os.arch: 'amd64', os.version: '3.13.0-48-generic', java.version: '1.8.0_20' Driver info: org.openqa.selenium.remote.RemoteWebDriver Capabilities [{applicationCacheEnabled=true, rotatable=false, handlesAlerts=true, databaseEnabled=true, version=38.0, platform=LINUX, nativeEvents=false, acceptSslCerts=true, webdriver.remote.sessionid=750ed820-db71-445a-b06e-8b50cce5b907, webStorageEnabled=true, locationContextEnabled=true, browserName=firefox, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}] Session ID: 750ed820-db71-445a-b06e-8b50cce5b907

What? not found in the cache ?
Các element đã được load và được hiện lên trên brower . Vậy cái gì không được tìm thấy trong cache.
Trước tiên thử xem Selenium nói gì về exception này

A stale element reference exception is thrown in one of two cases, the first being more common than the second:
The element has been deleted entirely.
The element is no longer attached to the DOM.

Selenium sẽ lưu toàn bộ Dom của website bạn đang test ở WebDriver. Mỗi khi bạn muốn thao tác hoặc kiểm tra một thành phần trên ứng dùng, webdriver sẽ tìm kiếm trong dom.
Theo selenium đưa ra lý do cho exception này là có vấn đề với state element . Dường như element trong webdriver không phải là element thực tế.
Giả sử bạn có 1 đoạn code sử dụng Ajax và jquery để ghi lại các Element. Và vấn đề xảy ra khi có một thao tác test của bạn kích hoạt đoạn code và tạo ra 1 element mới giống hoàn toàn với element cũ. (id class ...) . Và bước tiếp theo bạn sẽ thao tác tới các Element vừa mới ghi lại đó. Lúc này exception sẽ xảy ra nếu Element chưa update và vẫn sử dụng "cũ".

Hành động có kích hoạt đoạn ajax+jquery ${Step(submit.click)}
Kiểm tra dữ liệu hiện thị ( dữ liệu vừa đc fill mà không load lại page) ${abc must beDisplayed}

Làm thế nào để tránh được exception này ?
Để giải quyết vấn để này chúng ta phải tìm cách để thông báo hoặc BẮT webdriver câp nhật lại Dom 😃
Một giải pháp tôi tìm thấy trên các diễn dàn là sử dụng vòng lặp cho các element bạn tình nghi sẽ xảy ra exception này .
Cho tới thời điểm hiện tại, có hai giải pháp có thể giải quyết vấn đề này

  1. Find until load dom.
// This function will handle stalelement reference exception
 public void handleStaleElement(String elementName) {
  int count = 0;
  //It will try 4 times to find same element using name.
  while (count < 4) {
   try {
    //If exception generated that means It Is not able to find element then catch block will handle It.
    WebElement staledElement = driver.findElement(By.name(elementName));
    //If exception not generated that means element found and element text get cleared.
    staledElement.click();
   } catch (StaleElementReferenceException e) {
    e.toString();
    System.out.println("Trying to recover from a stale element :" + e.getMessage());
    count = count + 1;
   }
   count = count + 4;
  }
 }

Giải pháp trên có thể giải quyết được exception trên nhưng nó không tốt, chúng ta không biết nên sử dụng bao nhiêu vòng lặp là hợp lý .
2. Webdriver.refresh
Một giải pháp khác tôi đưa ra để giải quyết exception này là sử dụng webdriver.refresh() . Bạn gọi nó mỗi khi bạn cần webdriver cập nhật lại dom trong Webdriver

Hành động có kích hoạt đoạn ajax+jquery ${Step(submit.click)}
Load lại dom 							${webdriver.refresh()}
Kiểm tra dữ liệu hiện thị 				 ${abc must beDisplayed}

Với 2 cách nói trên các bạn có thể sử lý code tránh được exception nói trên.

All Rights Reserved