¿Cuándo usar la espera explícita frente a la espera implícita en Selenium Webdriver?

Estoy usando:

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

Pero todavía falla continuamente para el elemento a continuación

  driver.findElement(By.id("name")).clear(); driver.findElement(By.id("name")).sendKeys("Create_title_01"); 

He agregado el código de espera:

 for (int second = 0;; second++) { if (second >= 120) fail("timeout"); try { if (isElementPresent(By.id("name"))) break; } catch (Exception e) {} Thread.sleep(1000); } 

¿No debería esperar implícitamente a esperar hasta que se encuentre un elemento? También sería mejor si utilizo la espera explícita en lugar del código que he agregado que tiene Thread.sleep() ?

TL; DR: utilice siempre espera explícita. Olvida que existe una espera implícita.


Aquí hay un resumen rápido de las diferencias entre espera explícita e implícita:

Espera explícita:

  • comportamiento documentado y definido.
  • se ejecuta en la parte local de selenium (en el idioma de su código).
  • funciona en cualquier condición que se te ocurra
  • devuelve el error de éxito o de tiempo de espera.
  • puede definir la ausencia de elemento como condición de éxito.
  • puede personalizar la demora entre rebashs y excepciones para ignorar.

Espera implícita:

  • comportamiento indocumentado y prácticamente indefinido.
  • se ejecuta en la parte remota de selenium (la parte que controla el navegador).
  • solo funciona en los métodos de encontrar elemento (s).
  • devuelve el elemento encontrado o (después del tiempo de espera) no encontrado.
  • si se comprueba la ausencia de elemento siempre debe esperar hasta el tiempo de espera.
  • no se puede personalizar más que el tiempo de espera global.

Veamos la diferencia entre la espera explícita y la espera implícita en el código fuente real de selenium. Copié el código del enlace de python de selenium porque Python es “fácil de leer”.

El código de WebDriverWait.until() (espera explícita):

 def until(self, method, message=''): end_time = time.time() + self._timeout while(True): try: value = method(self._driver) if value: return value except self._ignored_exceptions: pass time.sleep(self._poll) if(time.time() > end_time): break raise TimeoutException(message) 

Ahora en lenguaje humano: esperar explícitamente espera un método que devuelve un valor truish si tiene éxito. Luego ejecuta repetidamente el método dado con un retraso en el medio. Los errores esperados del método dado son suprimidos. Si el método dado devuelve un valor truish, la espera explícita devolverá ese valor. Si el tiempo se agota, se genera una excepción de tiempo de espera.

Compare con el código de WebDriver.implicitly_wait() (comentarios eliminados por brevedad):

 def implicitly_wait(self, time_to_wait): self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) 

self.execute() es WebDriver.execute() que llama a RemoteConnection.execute() que a su vez, por lo que puedo decir, una RPC en el lado remoto del selenium.

En lenguaje humano: la espera implícita envía un mensaje al “lado remoto” del selenium webdriver. El lado remoto del Selenium webdriver es la parte del selenium que controla el navegador. ¿Qué hace el lado remoto con el mensaje? “Depende”. Depende del sistema operativo, del navegador y de la versión de selenium. Hasta donde puedo decir, no hay garantía sobre el comportamiento real de una implementación específica.

Posibles implementaciones son:

  • repetidamente intente encontrar el elemento hasta el tiempo de espera. regresa tan pronto como se encuentre el elemento.
  • Intenta encontrar el elemento. espere hasta el tiempo de espera. Inténtalo de nuevo.
  • espere hasta el tiempo de espera. Intenta encontrar el elemento.

Tenga en cuenta que la espera implícita solo tiene efecto en los métodos de buscar elemento (s).

No he buscado el código fuente real de los lados remotos del selenium. La información se recostack a partir de la lectura de los comentarios en los informes de errores sobre la espera en el selenium implícita y explícita :

Mi conclusión: la espera implícita es mala. Las capacidades son limitadas. El comportamiento no está documentado y depende de la implementación.

La espera explícita puede hacer todo lo que implícitamente puede esperar y más. La única desventaja de esperar explícitamente es un poco más sobrecarga debido a múltiples llamadas a procedimientos remotos. También la espera explícita es un poco más detallada. Pero esa verbosidad hace que el código sea explícito. Y explícito es mejor que implícito. ¿Derecha?


Otras lecturas:

Espera implícita : es una configuración global aplicable para todos los elementos y si el elemento aparece antes de la hora especificada, la secuencia de comandos comenzará a ejecutarse; de ​​lo contrario, la secuencia de comandos arrojará NoSuchElementException . La mejor forma de usarlo en el método de configuración. Solo afecta a By.findelement() .

Thread.sleep()Thread.sleep() tiempo para el script, no es una buena manera de usarlo en el script, ya que es sin condiciones. ¿Qué pasa si 2 segundos no son suficientes en el 5% de los casos?

Espera explícita : espere especificar el cambio de contenido / atributo. Se usa más cuando la aplicación proporciona una llamada AJAX al sistema y obtiene datos dynamics y los procesa en la interfaz de usuario. En este caso, WebDriverWait es adecuado.

¿Has probado fluentWait? Una implementación de la interfaz Wait que puede tener su tiempo de espera y el intervalo de sondeo configurado sobre la marcha. Cada instancia de FluentWait define la cantidad máxima de tiempo para esperar una condición, así como la frecuencia con la que se verifica la condición. Además, el usuario puede configurar la espera para ignorar tipos específicos de excepciones mientras espera, como NoSuchElementExceptions cuando busca un elemento en la página.

ver este enlace Descripción de la espera fluida

En particular, utilicé la espera fluida de esta manera:

 public WebElement fluentWait(final By locator){ Wait wait = new FluentWait(driver) .withTimeout(30, TimeUnit.SECONDS) .pollingEvery(5, TimeUnit.SECONDS) .ignoring(NoSuchElementException.class); WebElement foo = wait.until( new Function() { public WebElement apply(WebDriver driver) { return driver.findElement(locator); } } ); return foo; } ; 

Como ha notado, la espera fluida devuelve el elemento web encontrado. Así que simplemente pasa el localizador por tipo y luego puede realizar cualquier acción en el elemento web encontrado.

 fluentWait(By.id("name")).clear(); 

Espero que esto te ayude)

¿Has intentado usar ‘ WebDriverWait ‘? Imagino que lo que quieres es esto:

 WebDriverWait _wait = new WebDriverWait(driver, new TimeSpan(0, 0, 2)); //waits 2 secs max _wait.Until(d => d.FindElement(By.Id("name"))); //do your business on the element here :) 

Esto, a mi entender, hará prácticamente lo que tu código actual es. Probará constantemente el método (ignorando las excepciones no encontradas) hasta que se scope el tiempo de espera del intervalo de tiempo pasado y se pueda ingresar un tercer parámetro para especificar el tiempo de espera en milisegundos. ¡Lo siento si esto es lo que implícitamente espera también!

Editar: Leí algo hoy y entiendo mejor su pregunta y me doy cuenta de que esto hace exactamente lo que debería hacer su configuración de espera implícita. Lo dejaré aquí solo en caso de que el código en sí mismo pueda ayudar a alguien más.

ImplicitWait:

  1. Static Wait 2. UnConditional Wait. ( No Conditions were given) 3. Applicable throughout the program 

Declarando la espera implícita en java – selenium:

 driver.manage().timeout().implicitWait(20, TimeUnit.Seconds()); 

Espera explícita:

  1. Espera dinámica
  2. Espera condicional
  3. No aplicable en todo el progtwig

Declarando la espera explícita en Java Selenium.

 WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition); 

Las esperas implícitas se utilizan para proporcionar un tiempo de espera (digamos 30 segundos) entre cada paso de prueba consecutiva en todo el guión o progtwig de prueba. El siguiente paso solo se ejecuta cuando transcurren los 30 segundos (o el tiempo que haya transcurrido) después de la ejecución del paso anterior

Sintaxis:

 WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); 

Las esperas explícitas se utilizan para detener la ejecución hasta el momento en que se cumple una condición particular o transcurre el tiempo máximo definido. La espera implícita se aplicó entre cada paso de prueba consecutiva en toda la secuencia de comandos de prueba o los progtwigs, mientras que las Esperas explícitas se aplican solo a una instancia en particular.

Sintaxis:

 WebDriver driver = new FirefoxDriver(); WebDriverWait wait = new WebDriverWait(driver,30);