¿Cómo puedo pedirle al Selenium-WebDriver que espere unos segundos en Java?

Estoy trabajando en Java Selenium-WebDriver. yo añadí

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

y

 WebElement textbox = driver.findElement(By.id("textbox")); 

porque mis aplicaciones tardan unos segundos en cargar la interfaz de usuario. Así que establecí 2 segundos de espera implícita. pero no pude localizar el cuadro de texto del elemento

Luego agrego Thread.sleep(2000);

Ahora funciona bien. ¿Cuál es una mejor manera?

Bueno, hay dos tipos de espera: espera explícita e implícita. La idea de espera explícita es

 WebDriverWait.until(condition-that-finds-the-element); 

El concepto de espera implícita es

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

Puede obtener la diferencia en los detalles aquí .

En tales situaciones, preferiría usar wait explícito ( fluentWait en particular):

 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; }; 

fluentWait función fluentWait devuelve el elemento web encontrado. De la documentación en 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. Detalles que puedes obtener aquí

El uso de fluentWait en su caso será el siguiente:

 WebElement textbox = fluentWait(By.id("textbox")); 

En mi opinión, esto es mejor ya que no sabes exactamente cuánto tiempo esperar y en el intervalo de sondeo puedes establecer un valor de tiempo arbitrario a través del cual se verificará la presencia del elemento. Saludos.

Si usa webdriverJs (node.js),

 driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() { driver.sleep(5000); }); 

El código anterior hace que el navegador espere 5 segundos después de hacer clic en el botón.

Este hilo es un poco más antiguo, pero pensé que publicaría lo que hago actualmente (trabajo en progreso).

Aunque todavía estoy en situaciones donde el sistema está bajo mucha carga y cuando hago clic en un botón de enviar (por ejemplo, login.jsp), las tres condiciones (ver a continuación) devuelven true pero la siguiente página (por ejemplo, home.jsp) hasn ‘t comenzó a cargar todavía.

Este es un método de espera genérico que toma una lista de Condicionesesperadas.

 public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition... conditions) { boolean isLoaded = false; Wait wait = new FluentWait<>(driver) .withTimeout(waitTimeInSec, TimeUnit.SECONDS) .ignoring(StaleElementReferenceException.class) .pollingEvery(2, TimeUnit.SECONDS); for (ExpectedCondition condition : conditions) { isLoaded = wait.until(condition); if (isLoaded == false) { //Stop checking on first condition returning false. break; } } return isLoaded; } 

He definido varias condiciones esperadas reutilizables (tres están por debajo). En este ejemplo, las tres condiciones esperadas incluyen document.readyState = ‘complete’, no hay un “wait_dialog” presente y no hay ‘spinners’ (elementos que indican que se están solicitando datos asíncronos).

Solo el primero se puede aplicar genéricamente a todas las páginas web.

 /** * Returns 'true' if the value of the 'window.document.readyState' via * JavaScript is 'complete' */ public static final ExpectedCondition EXPECT_DOC_READY_STATE = new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }"; Boolean result; try { result = ((JavascriptExecutor) driver).executeScript(script).equals("complete"); } catch (Exception ex) { result = Boolean.FALSE; } return result; } }; /** * Returns 'true' if there is no 'wait_dialog' element present on the page. */ public static final ExpectedCondition EXPECT_NOT_WAITING = new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { Boolean loaded = true; try { WebElement wait = driver.findElement(By.id("F")); if (wait.isDisplayed()) { loaded = false; } } catch (StaleElementReferenceException serex) { loaded = false; } catch (NoSuchElementException nseex) { loaded = true; } catch (Exception ex) { loaded = false; System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage()); } return loaded; } }; /** * Returns true if there are no elements with the 'spinner' class name. */ public static final ExpectedCondition EXPECT_NO_SPINNERS = new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { Boolean loaded = true; try { List spinners = driver.findElements(By.className("spinner")); for (WebElement spinner : spinners) { if (spinner.isDisplayed()) { loaded = false; break; } } }catch (Exception ex) { loaded = false; } return loaded; } }; 

Dependiendo de la página, puedo usar uno o todos:

 waitForPageLoad(timeoutInSec, EXPECT_DOC_READY_STATE, EXPECT_NOT_WAITING, EXPECT_NO_SPINNERS ); 

También hay ExpectedConditions predefinidos en la siguiente clase: org.openqa.selenium.support.ui.ExpectedConditions

Usando Thread.sleep(2000); es una espera incondicional. Si su prueba se carga más rápido, igual tendrá que esperar. Entonces, en principio, usar implicitlyWait es la mejor solución.

Sin embargo, no veo por qué implicitlyWait Espera no funciona en su caso. ¿ findElement si el findElement realidad lleva dos segundos antes de lanzar una excepción? De ser así, ¿puedes intentar usar la espera condicional de WebDriver como se describe en esta respuesta?

Me gusta usar condiciones personalizadas. Aquí hay un código en Python:

 def conditions(driver): flag = True ticker = driver.find_elements_by_id("textbox") if not ticker: flag = False return flag ... click something to load ... self.wait = WebDriverWait(driver, timeout) self.wait.until(conditions) 

Siempre que necesite esperar, puede hacerlo de forma explícita comprobando la existencia de un determinado elemento (tal elemento puede variar de una página a otra). find_elements_by_id lista de devoluciones – vacía o no, solo tiene que verificar.

¿Parece que el clic está bloqueando? – Aquí hay otra manera de esperar si está usando WebDriverJS:

 driver.findElement(webdriver.By.name('mybutton')).click().then(function(){ driver.getPageSource().then(function(source) { console.log(source); }); }); 

El código anterior espera después de que se hace clic en el botón para cargar la página siguiente y luego toma el origen de la página siguiente.

 Thread.sleep(5000); 

Esto sí me ayudó, pero la excepción InterruptedException necesita ser atendida. Así que mejor rodearlo con try y catch:

 try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } 

O

Agregar statement de lanzamientos:

 public class myClass { public static void main(String[] args) throws InterruptedException { ... } 

Preferiría el segundo ya que uno puede usar sleep() tantas veces como lo desee y evitar la repetición de try y catch block cada vez que se use sleep() .

A veces, la espera implícita parece anulada y el tiempo de espera se acorta. [@ eugene.polschikov] tenía buena documentación sobre los por qué. He encontrado en mi prueba y encoding con Selenium 2 que las esperas implícitas son buenas pero ocasionalmente tienes que esperar explícitamente.

Es mejor evitar llamar directamente a un hilo para dormir, pero a veces no hay una buena forma de evitarlo. Sin embargo, hay otras opciones de espera proporcionadas por Selenium que ayudan. waitForPageToLoad y waitForFrameToLoad han demostrado ser especialmente útiles.

Espera implícitamente y Thread.sleep Both se usan solo para la sincronización … pero la diferencia es que podemos usar Implícitamente espere todo el progtwig, pero Thread.sleep funcionará solo para ese código. Aquí mi sugerencia es usar Implícitamente espere una vez en el progtwig cuando cada vez que su página web se renueve significa usar Thread.sleep en ese momento … será mucho mejor 🙂

Aquí está mi código:

 package beckyOwnProjects; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.interactions.Actions; public class Flip { public static void main(String[] args) throws InterruptedException { WebDriver driver=new FirefoxDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES); driver.get("https://www.flipkart.com"); WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block")); Actions act=new Actions(driver); Thread.sleep(5000); act.moveToElement(ele).perform(); } } 

Espera implícita: durante la espera implícita si el controlador web no puede encontrarlo inmediatamente debido a su disponibilidad, el WebDriver esperará la hora mencionada y no intentará encontrar el elemento nuevamente durante el período de tiempo especificado. Una vez que ha pasado el tiempo especificado, intentará buscar el elemento una vez más la última vez antes de lanzar la excepción. La configuración predeterminada es cero. Una vez que establecemos un horario, el Controlador Web espera el período de la instancia del objeto WebDriver.

Espera explícita: puede haber una instancia cuando un elemento en particular tarda más de un minuto en cargarse. En ese caso, definitivamente no le gustaría dedicar mucho tiempo a la espera implícita, ya que si hace esto, su navegador esperará al mismo tiempo para cada elemento. Para evitar esa situación, simplemente puede poner un tiempo por separado solo en el elemento requerido. Siguiendo esto, el tiempo de espera implícito de su navegador sería corto para cada elemento y sería grande para un elemento específico.

En ocasiones, la espera implícita falla y dice que existe un elemento pero realmente no.

La solución es evitar el uso de driver.findElement y reemplazarlo con un método personalizado que utilice una espera explícita implícitamente. Por ejemplo:

 import org.openqa.selenium.NoSuchElementException; public WebElement element(By locator){ Integer timeoutLimitSeconds = 20; WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds); try { wait.until(ExpectedConditions.presenceOfElementLocated(locator)); } catch(TimeoutException e){ throw new NoSuchElementException(locator.toString()); } WebElement element = driver.findElement(locator); return element; } 

Hay razones adicionales para evitar la espera implícita que no sean fallas esporádicas y ocasionales (consulte este enlace ).

Puede usar este método de “elemento” de la misma manera que driver.findElement. Por ejemplo:

  driver.get("http://yoursite.html"); element(By.cssSelector("h1.logo")).click(); 

Si realmente desea esperar unos segundos para la solución de problemas o alguna otra ocasión rara, puede crear un método de pausa similar al que ofrece el IDE de selenium:

  public void pause(Integer milliseconds){ try { TimeUnit.MILLISECONDS.sleep(milliseconds); } catch (InterruptedException e) { e.printStackTrace(); } } 

Respuesta : espere unos segundos antes de que la visibilidad del elemento utilizando Selenium WebDriver vaya por debajo de los métodos.

implicitlyWait () : la instancia de WebDriver espera hasta la carga de la página completa. Debes usar de 30 a 60 segundos para esperar la carga de la página completa.

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

Espera explícitamente WebDriverWait () : la instancia de WebDriver espera hasta la carga de la página completa.

 WebDriverWait wait = new WebDriverWait(driver, 60); wait.until(ExpectedConditions.visibilityOf(textbox)); driver.findElement(By.id("Year")).sendKeys(allKeys); 

Nota : utilice explícitamente el WebDriverWait () para manejar cualquier WebElement en particular.

Prefiero el siguiente código para esperar 2 segundos.

 for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){ Thread.sleep(1000); } 
 Thread.sleep(1000); 

es peor: al ser una espera estática, hará que el script de prueba sea más lento.

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

esta es una espera dinámica

  • es válido hasta la existencia del disco web o tiene un scope hasta la duración del controlador
  • también podemos esperar implícitamente.

Finalmente, lo que sugiero es

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

con algunas condiciones predefinidas:

 isAlertPresent(); elementToBeSelected(); visibilityOfElementLocated(); visibilityOfAllElementLocatedBy(); frameToBeAvailableAndSwitchToIt(); 
  • También es una espera dinámica
  • en esto, la espera solo será en segundos
  • tenemos que usar espera explícita para un elemento web particular en el que queremos usar.
 public static void waitForElement(WebDriver driver)throws Exception { driver.findElement(By.xpath("//table")).sendKeys //line1(org.openqa.selenium.Keys.CONTROL); Thread.sleep(500); } 

Use este código en caso de que la página se actualice cuando cambie el control de un campo de entrada a otro campo de entrada dentro de la misma página. Pase la referencia del controlador correspondiente a este método para encontrar el elemento. Line1 se usa para hacer clic afuera que hace la actualización. Si tiene alguna consulta, publique su comentario.