Espero que sea solo yo, pero Selenium Webdriver parece una pesadilla completa. El controlador web Chrome actualmente no se puede usar, y los otros controladores son poco confiables, o eso parece. Estoy luchando contra muchos problemas, pero aquí hay uno.
Aleatoriamente, mis pruebas fallarán con un
"org.openqa.selenium.StaleElementReferenceException: Element is no longer attached
to the DOM
System info: os.name: 'Windows 7', os.arch: 'amd64',
os.version: '6.1', java.version: '1.6.0_23'"
Estoy usando webdriver versiones 2.0b3. He visto que esto sucede con los controladores FF e IE. La única forma en que puedo evitar esto es agregar una llamada real Thread.sleep
antes de que ocurra la excepción. Sin embargo, esa es una solución alternativa deficiente, así que espero que alguien pueda señalar un error de mi parte que mejorará todo esto.
java
selenium-webdriver
webdriver
automated-tests
Ray Nicholus
fuente
fuente
from selenium.common.exceptions import NoSuchElementException
Respuestas:
Sí, si tiene problemas con StaleElementReferenceExceptions es porque sus pruebas están mal escritas. Es una condición de carrera. Considere el siguiente escenario:
Ahora, en el punto donde hace clic en el elemento, la referencia del elemento ya no es válida. Es casi imposible para WebDriver hacer una buena suposición sobre todos los casos en que esto podría suceder, por lo que levanta las manos y le da el control a usted, que como autor de la prueba / aplicación debe saber exactamente qué puede o no suceder. Lo que desea hacer es esperar explícitamente hasta que el DOM esté en un estado en el que sepa que las cosas no cambiarán. Por ejemplo, usando un WebDriverWait para esperar a que exista un elemento específico:
El método presenciaOfElementoLocalizado () se vería así:
Tiene toda la razón acerca de que el controlador Chrome actual es bastante inestable, y le alegrará saber que el tronco Selenium tiene un controlador Chrome reescrito, donde los desarrolladores de Chromium realizaron la mayor parte de la implementación como parte de su árbol.
PD. Alternativamente, en lugar de esperar explícitamente como en el ejemplo anterior, puede habilitar las esperas implícitas, de esta manera WebDriver siempre se repetirá hasta el tiempo de espera especificado esperando que el elemento esté presente:
Sin embargo, en mi experiencia, esperar explícitamente siempre es más confiable.
fuente
com.google.common.base.Function<F, T>
proporcionado por Guava .He podido usar un método como este con cierto éxito:
Sí, solo sigue sondeando el elemento hasta que ya no se considera rancio (¿fresco?). Realmente no llega a la raíz del problema, pero he descubierto que WebDriver puede ser bastante exigente al lanzar esta excepción: a veces lo entiendo, y otras no. O podría ser que el DOM realmente está cambiando.
Así que no estoy del todo de acuerdo con la respuesta anterior de que esto necesariamente indica una prueba mal escrita. Lo tengo en páginas nuevas con las que no he interactuado de ninguna manera. Creo que hay algunas fallas en la forma en que se representa el DOM o en lo que WebDriver considera obsoleto.
fuente
A veces aparece este error cuando las actualizaciones de AJAX están a mitad de camino. Capybara parece ser bastante inteligente al esperar los cambios de DOM (consulte Por qué wait_until fue eliminado de Capybara ), pero el tiempo de espera predeterminado de 2 segundos simplemente no fue suficiente en mi caso. Cambiado en _spec_helper.rb_ con eg
fuente
Hoy me enfrentaba al mismo problema e hice una clase de contenedor, que verifica antes de cada método si la referencia del elemento sigue siendo válida. Mi solución para recuperar el elemento es bastante simple, así que pensé en compartirlo.
Verá que "localizo" o, más bien, guardo el elemento en una variable global js y recupere el elemento si es necesario. Si la página se vuelve a cargar, esta referencia ya no funcionará. Pero siempre y cuando solo se hagan cambios para condenar, la referencia permanece. Y eso debería hacer el trabajo en la mayoría de los casos.
También evita volver a buscar el elemento.
Juan
fuente
Tuve el mismo problema y el mío fue causado por una antigua versión de selenio. No puedo actualizar a una versión más nueva debido al entorno de desarrollo. El problema es causado por HTMLUnitWebElement.switchFocusToThisIfNeeded (). Cuando navega a una página nueva, puede suceder que el elemento en el que hizo clic en la página anterior sea el
oldActiveElement
(consulte a continuación). Selenium intenta obtener el contexto del elemento antiguo y falla. Es por eso que construyeron un intento de captura en futuras versiones.Código de selenium-htmlunit-driver versión <2.23.0:
Código de la versión del controlador selenio-htmlunit> = 2.23.0:
Sin actualizar a 2.23.0 o más reciente, puede asignar cualquier elemento al foco de la página. Acabo de usar
element.click()
por ejemplo.fuente
Me acaba de ocurrir cuando intento enviar_claves a un cuadro de entrada de búsqueda, que tiene una actualización automática según lo que escriba. Como mencionó Eero, esto puede suceder si su elemento actualiza Ajax mientras está escribiendo su texto dentro del elemento de entrada . La solución es enviar un carácter a la vez y buscar nuevamente el elemento de entrada . (Ej. En rubí se muestra a continuación)
fuente
Para agregar a la respuesta de @ jarib, he hecho varios métodos de extensión que ayudan a eliminar la condición de carrera.
He aquí mi arreglo:
Tengo una clase llamada "Driver.cs". Contiene una clase estática llena de métodos de extensión para el controlador y otras funciones estáticas útiles.
Para los elementos que normalmente necesito recuperar, creo un método de extensión como el siguiente:
Esto le permite recuperar ese elemento de cualquier clase de prueba con el código:
Ahora, si esto resulta en a
StaleElementReferenceException
, tengo el siguiente método estático en mi clase de controlador:El primer parámetro de esta función es cualquier función que devuelve un objeto IWebElement. El segundo parámetro es un tiempo de espera en segundos (el código para el tiempo de espera se copió del Selenium IDE para FireFox). El código se puede usar para evitar la excepción del elemento obsoleto de la siguiente manera:
El código anterior llamará
driver.SpecificElementToGet().Displayed
hasta quedriver.SpecificElementToGet()
no arroje excepciones y.Displayed
evalúetrue
y no hayan pasado 5 segundos. Después de 5 segundos, la prueba fallará.Por otro lado, para esperar a que un elemento no esté presente, puede usar la siguiente función de la misma manera:
fuente
Creo que encontré un enfoque conveniente para manejar StaleElementReferenceException. Por lo general, debe escribir contenedores para cada método WebElement para volver a intentar acciones, lo cual es frustrante y desperdicia mucho tiempo.
Agregar este código
antes de que cada acción de WebElement pueda aumentar la estabilidad de sus pruebas, pero aún puede obtener StaleElementReferenceException de vez en cuando.
Entonces esto es lo que se me ocurrió (usando AspectJ):
Para habilitar este aspecto, cree un archivo
src\main\resources\META-INF\aop-ajc.xml
y escribaAgregue esto a su
pom.xml
Y eso es todo. Espero eso ayude.
fuente
Puede resolver esto usando la espera explícita para no tener que usar la espera dura.
Si obtiene todos los elementos con una propiedad e itera a través de ella usando cada ciclo, puede usar esperar dentro del ciclo de esta manera,
o para un solo elemento puede usar el siguiente código,
fuente
En Java 8 puede usar un método muy simple para eso:
fuente
fuente