2013-04-15 7 views
5

Strona zawiera niektóre dane (tabela z kilkoma wierszami). Jest przycisk "odśwież", który przeładowuje i przerysowuje niektóre elementy na stronie bez przeładowywania danych statycznych (ajax).selenium.common.exceptions.StaleElementReferenceException podczas odświeżania strony

Próbuję utworzyć poprawny test dla tej strony, ale czasami pojawia się wyjątek StaleElementReferenceException.

Mój kod (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 5 iteracjach nie on line "jeśli nie 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 

Głównym problemem: strona zawiera już poprzednie dane , więc dostaję wyścig pomiędzy odświeżeniem ajaxowym a zapytaniem o element webdrivera pod numerem find_elements_by_class_name('datarow').

Jak mogę poprawnie rozwiązać wyścig między odświeżaniem ajax a webdriverem? Dzięki.

Odpowiedz

3

nieświeży wyjątkiem odniesienia elementu jest wyrzucane w dwóch przypadkach, z których pierwsza jest bardziej powszechne niż drugiego

  • element został całkowicie usunięty.
  • Element nie jest już dołączony do DOM

Proszę przejść przez poniższej dokumentacji selenu, aby uzyskać więcej informacji

Stale element reference exception documentation

+0

Rozumiem ogólny pomysł na Stale problem, ale chcę znaleźć dobry sposób na uniknięcie tego, bez niekończącego się "try/except". –

+0

Spróbuj użyć innego rodzaju lokalizatorów. – Hemanth

4

Obawiam się, że nie może pomóc wiążące pyton. Mogę jednak pomóc w ogólnych poradach dotyczących WebDriver i niektórych fragmentów kodu Java, które mogą pomóc (innym) w znalezieniu ich odpowiednika w języku Python. Istnieje kilka rzeczy, z którymi możesz poradzić sobie z AJAX w Selenie.

1. Niejawne czekanie- To spowoduje, że sterownik sieci internetowej będzie odpytywał DOM przez określony czas.

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

2. Jawne czeka - Wolę tych! Można ich używać w połączeniu z dorozumianym czekaniem. Możesz powiedzieć WebDriver, aby oczekiwał na pewien warunek. Musisz użyć WebDriverWait, aby użyć jawnego czekania.

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

ExpectedConditions zapewnia wiele warunków oczekiwania za darmo i uważam, że jest to niezwykle przydatne.

Gdybym miał napisać powyższy fragment kodu w Javie, zrobiłbym poniżej. Uwaga: Napisałem to w edytorze, więc powinno się skompilować. Myślę, że da ci to pomysł na korzystanie z 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"); 
      } 
} 

Wreszcie, z mojego doświadczenia wynika, że ​​wiele nowoczesnych aplikacji AJAX korzysta z jQuery. Z powodzeniem używam flagi jQuery.active przez kilka lat, aby sprawdzić, czy strona jest załadowana, czy nie. Możesz połączyć to ze zwykłym javascript document.readyState. Jest to ogólna metoda, której używam do czekania po każdym "kliknięciu" dla moich aplikacji 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);