2013-04-15 31 views
5

Trang chứa một số dữ liệu (bảng có vài hàng). Có nút 'refresh' để tải lại và vẽ lại một số phần tử trên trang mà không cần tải lại dữ liệu tĩnh (ajax).selenium.common.exceptions.StaleElementReferenceException trong khi làm mới trang

Tôi đang cố tạo thử nghiệm thích hợp cho trang đó, nhưng thỉnh thoảng nhận được StaleElementReferenceException.

Mã của tôi (python):

from selenium import webdriver 
browser=webdriver.Firefox() 
browser.get('http://mytisite') 
browser.implicitly_wait(10) 
browser.find_element_by_id('start').click() 
while browser.find_element_by_id('status').text!='Done': 
    browser.find_element_by_id('refresh').click() 
    for row in browser.find_elements_by_class_name('datarow'): 
     if not is_correct(row.text): 
      print "incorrect" 
    time.sleep(10) 

1 của 5 lặp lại thất bại trên đường dây "nếu không muốn nói is_correct (row.text)":

selenium.common.exceptions.StaleElementReferenceException: 
Message: u'Element not found in the cache - perhaps the page 
has changed since it was looked up' ; Stacktrace: Method 
fxdriver.cache.getElementAt threw an error in 
resource://fxdriver/modules/web_element_cache.js 

vấn đề chính: trang đã có chứa dữ liệu trước đó , vì vậy tôi nhận được cuộc đua giữa làm mới ajax và truy vấn phần tử webdriver của find_elements_by_class_name('datarow').

Tôi có thể giải quyết đúng cách cuộc đua giữa làm mới ajax và trình quản trị web? Cảm ơn.

Trả lời

3

Một cũ ngoại lệ tham khảo phần tử được ném vào một trong hai trường hợp, đầu tiên là phổ biến hơn so với thứ hai:

  • Yếu tố đã bị xóa hoàn toàn.
  • Yếu tố không còn gắn liền với DOM

xin vui lòng đi qua các tài liệu hướng dẫn selen dưới đây để biết thêm

Stale element reference exception documentation

+0

Tôi hiểu ý tưởng chung đằng sau vấn đề cũ, nhưng tôi muốn tìm một số cách tốt đẹp để tránh nó, mà không cần bất tận 'try/except'. –

+0

Thử sử dụng các loại định vị khác. – Hemanth

4

tôi sợ, tôi không thể giúp bạn với python ràng buộc. Tuy nhiên tôi có thể giúp bạn với lời khuyên chung về WebDriver và một số đoạn mã Java có thể giúp bạn (những người khác) dẫn đến tìm thấy tương đương python của họ. Có rất nhiều thứ bạn có thể làm với AJAX trong Selenium.

1. Implicit waits- Điều này sẽ cho trình điều khiển web thăm dò ý kiến ​​DOM trong một khoảng thời gian nhất định.

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

2. Rõ ràng waits - Tôi thích những thứ này! Người ta có thể sử dụng chúng kết hợp với chờ đợi tiềm ẩn. Bạn có thể yêu cầu WebDriver đợi điều kiện nhất định. Bạn cần sử dụng WebDriverWait để sử dụng thời gian chờ rõ ràng.

WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/); 
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("refresh"))); 

ExpectedConditions cung cấp nhiều điều kiện chờ miễn phí và tôi thấy nó cực kỳ hữu ích.

Nếu tôi viết đoạn mã trên của bạn bằng Java, tôi sẽ làm bên dưới. Lưu ý tôi đã viết điều này trong một trình soạn thảo, vì vậy nó sẽ biên dịch. Tôi đoán điều này sẽ cung cấp cho bạn một ý tưởng về việc sử dụng WebDriverWait.

WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/); 
ExpectedCondition<Boolean> untilIFindStatus = ExpectedConditions 
        .elementToBeSelected(By.id("status")); 
while (wait.until(untilIFindStatus)) { 
     WebElement refresh = wait.until(ExpectedConditions 
         .elementToBeClickable(By.id("refresh"))); 
     refresh.click(); 
     List<WebElement> allRows = wait.until(ExpectedConditions 
       .presenceOfAllElementsLocatedBy(By.className("datarow"))); 
      for (WebElement row : allRows) { 
       if (row.getText().equals("awesome")) 
        System.out.println("do something"); 
      } 
} 

Cuối cùng, trong kinh nghiệm của tôi, nhiều ứng dụng AJAX hiện đại sử dụng jQuery. Tôi đã sử dụng cờ jQuery.active trong vài năm thành công để kiểm tra xem trang có được tải hay không. Bạn có thể kết hợp điều đó với javascript đơn giản document.readyState. Đây là phương pháp chung tôi sử dụng để chờ sau mỗi lần nhấp vào '' cho các ứng dụng AJAX của tôi.

ExpectedCondition<Boolean> jQueryActive_toBeZero = new ExpectedCondition<Boolean>() { 
     public Boolean apply(WebDriver driver) { 
      try { 
      return ((Long) jsExecutor 
       .executeScript("return jQuery.active") == 0) ? true 
          : false; 
     } catch (WebDriverException e) { 
      log.debug("It looks like jQuery is not available on the page, skipping the jQuery wait, check stack trace for details"); 
      return true; //skip the wait 
     } 
      } 
     }; 
ExpectedCondition<Boolean> document_readyState_toBeComplete = new ExpectedCondition<Boolean>() { 
     public Boolean apply(WebDriver driver) { 
      return jsExecutor.executeScript("return document.readyState") 
      .toString().equals("complete") ? true : false; 
     } 
    }; 
    wait.until(jQueryActive_toBeZero); 
    wait.until(document_readyState_toBeComplete); 
Các vấn đề liên quan