2013-04-15 6 views
5

Страница содержит некоторые данные (таблица с несколькими строками). Существует кнопка «Обновить», которая перезагружает и перерисовывает некоторые элементы на странице без перезагрузки статических данных (ajax).selenium.common.exceptions.StaleElementReferenceException при обновлении страницы

Я пытаюсь создать правильный тест для этой страницы, но иногда получаю исключение StaleElementReferenceException.

Мой код (питон):

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 из 5 итераций не будет работать на линии "если не 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 

Главная проблема: страница уже содержит предыдущие данные , поэтому я получаю гонку между обновлением ajax и элементом элемента webdriver от find_elements_by_class_name('datarow').

Как я могу правильно решить гонку между обновлением ajax и webdriver? Благодарю.

ответ

3

несвежий опорный элемент, исключение в одном из двух случаев, первый из которых более распространенным, чем вторая:

  • Элемент был удален полностью.
  • Элемент больше не прикреплен к DOM

пожалуйста, пройти через документацию ниже селена для получения дополнительной информации

Stale element reference exception documentation

+0

Я понимаю общую идею, стоящую за проблемой Стайл, но я хочу найти хороший способ избежать этого, без бесконечных «try/except». –

+0

Попробуйте использовать другие типы локаторов. – Hemanth

4

Боюсь, я не могу помочь вам с обязательным питоном. Однако я могу помочь вам в общих советах по WebDriver и некоторых фрагментах Java, которые могут помочь вам (другим) найти их эквивалент python. Есть несколько вещей, которые вы можете сделать с AJAX в Selenium.

1. Неявные ожидания - Это скажет веб-драйверу опроса DOM на определенный период.

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

2. Явные ждет - Я предпочитаю это! Их можно использовать в сочетании с неявным ожиданием. Вы можете сказать, что WebDriver ждет определенного состояния. Вам нужно использовать WebDriverWait для использования явных ожиданий.

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

ExpectedConditions предоставляет множество условий ожидания бесплатно, и я нахожу это чрезвычайно полезно.

Если бы я написал ваш фрагмент кода в Java, я бы сделал ниже. Примечание. Я написал это в редакторе, поэтому он должен компилироваться. Думаю, это даст вам представление об использовании 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"); 
      } 
} 

Наконец, по моему опыту многие современные приложения AJAX используют jQuery. Я успешно использовал флаг jQuery.active в течение нескольких лет, чтобы проверить, загружена ли страница или нет. Вы можете комбинировать это с простым javascript document.readyState. Это общий метод, который я использую для ожидания после каждого нажатия на мои приложения AJAX.

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); 
Смежные вопросы