Mira la lección en vídeo
Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.
Desbloquear Plan PlusQué es FluentWait
FluentWait representa la versión más avanzada y configurable de las esperas en Selenium WebDriver, proporcionando un control granular sobre todos los aspectos del comportamiento de espera. A diferencia de WebDriverWait, que ofrece una configuración básica, FluentWait permite personalizar cada detalle del proceso de espera mediante una interfaz fluida que facilita la construcción de esperas complejas.
Esta clase implementa el patrón Builder y extiende la funcionalidad de Wait
Arquitectura y configuración
La arquitectura de FluentWait se basa en una cadena de métodos que permiten configurar cada aspecto del comportamiento de espera:
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(NoSuchElementException.class);
El tipo genérico FluentWait<T>
permite trabajar no solo con WebDriver, sino con cualquier tipo de objeto sobre el cual queramos aplicar condiciones de espera. Esta flexibilidad hace que FluentWait sea útil más allá de la automatización web tradicional.
Parámetros de configuración principales
FluentWait expone varios métodos de configuración que definen su comportamiento:
withTimeout(Duration)
: establece el tiempo máximo que FluentWait esperará antes de lanzar una TimeoutExceptionpollingEvery(Duration)
: define el intervalo entre cada verificación de la condiciónignoring(Class<? extends Throwable>)
: especifica qué excepciones deben ser ignoradas durante las verificacioneswithMessage(String)
: personaliza el mensaje de error que se mostrará si la espera falla
La sintaxis moderna utiliza la clase Duration
de Java Time API, reemplazando los antiguos métodos que requerían valores numéricos y unidades separadas:
// Sintaxis moderna con Duration
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofMillis(500))
// En lugar de la sintaxis legacy
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS)
Ventajas sobre WebDriverWait
FluentWait ofrece varias ventajas significativas sobre WebDriverWait:
- Control granular del polling: permite ajustar con precisión el intervalo entre verificaciones, optimizando el rendimiento según las necesidades específicas
- Gestión de excepciones personalizada: posibilidad de ignorar múltiples tipos de excepciones específicas durante el proceso de espera
- Mensajes de error personalizados: facilita la depuración mediante mensajes descriptivos cuando las esperas fallan
- Flexibilidad de tipos: no está limitado a WebDriver, puede trabajar con cualquier tipo de objeto
Casos de uso ideales
FluentWait resulta especialmente útil en escenarios que requieren un control detallado del proceso de espera:
- Aplicaciones con tiempos de carga variables: cuando diferentes elementos requieren intervalos de polling distintos
- Integración con APIs externas: donde pueden producirse diferentes tipos de excepciones temporales
- Condiciones de espera complejas: que involucran múltiples elementos o estados de la aplicación
- Optimización de rendimiento: cuando necesitamos ajustar finamente los tiempos de espera para diferentes entornos
La naturaleza configurable de FluentWait lo convierte en la opción preferida para equipos que requieren un control preciso sobre el comportamiento de las esperas, especialmente en aplicaciones empresariales donde la estabilidad y el rendimiento son críticos.
Ejemplos de FluentWait
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
Configuración básica con múltiples parámetros
El siguiente ejemplo muestra cómo configurar FluentWait con todos sus parámetros principales en una prueba real:
@Test
void deberiaEsperarElementoConConfiguracionCompleta() {
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(NoSuchElementException.class)
.ignoring(ElementNotInteractableException.class)
.withMessage("El botón de confirmación no apareció en el tiempo esperado");
WebElement botonConfirmar = wait.until(driver ->
driver.findElement(By.id("confirm-button"))
);
botonConfirmar.click();
}
Este ejemplo demuestra cómo FluentWait permite ignorar múltiples excepciones simultáneamente, algo especialmente útil cuando trabajamos con elementos que pueden no estar disponibles o no ser interactuables durante períodos específicos.
Espera con condiciones personalizadas
FluentWait brilla cuando necesitamos implementar condiciones de espera complejas que van más allá de la simple presencia de elementos:
@Test
void deberiaEsperarCargaCompletaDeTabla() {
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(45))
.pollingEvery(Duration.ofMillis(500))
.ignoring(StaleElementReferenceException.class);
// Condición personalizada: tabla debe tener al menos 10 filas
List<WebElement> filas = wait.until(driver -> {
List<WebElement> elementos = driver.findElements(By.cssSelector("table tbody tr"));
return elementos.size() >= 10 ? elementos : null;
});
assertThat(filas).hasSizeGreaterThanOrEqualTo(10);
}
La función lambda permite definir lógica personalizada que se ejecuta en cada iteración del polling. El retorno de null
indica que la condición aún no se cumple, mientras que cualquier otro valor significa éxito.
Control granular del polling para elementos dinámicos
En aplicaciones con contenido dinámico, el intervalo de polling puede ser crítico para el rendimiento:
@Test
void deberiaOptimizarPollingParaNotificaciones() {
// Polling frecuente para notificaciones que aparecen rápidamente
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(100))
.ignoring(NoSuchElementException.class);
WebElement notificacion = wait.until(ExpectedConditions.presenceOfElementLocated(
By.className("notification-success")
));
String mensaje = notificacion.getText();
assertThat(mensaje).contains("Operación completada exitosamente");
}
El polling cada 100 milisegundos permite capturar notificaciones que aparecen y desaparecen rápidamente, algo que sería difícil de lograr con intervalos más largos.
Espera de múltiples condiciones simultáneas
FluentWait permite crear condiciones complejas que evalúan múltiples criterios:
@Test
void deberiaEsperarEstadoCompletoFormulario() {
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(20))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(NoSuchElementException.class, ElementNotInteractableException.class);
// Esperar que el formulario esté completamente listo
Boolean formularioListo = wait.until(driver -> {
WebElement submitButton = driver.findElement(By.id("submit"));
WebElement loadingSpinner = driver.findElements(By.className("loading")).isEmpty() ? null
: driver.findElement(By.className("loading"));
WebElement errorMessage = driver.findElements(By.className("error")).isEmpty() ? null
: driver.findElement(By.className("error"));
return submitButton.isEnabled() &&
(loadingSpinner == null || !loadingSpinner.isDisplayed()) &&
(errorMessage == null || !errorMessage.isDisplayed());
});
assertTrue(formularioListo);
}
Manejo de excepciones específicas del contexto
Diferentes contextos de aplicación requieren ignorar excepciones específicas. FluentWait permite una configuración precisa:
@Test
void deberiaGestionarExcepcionesSPA() {
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(StaleElementReferenceException.class) // SPA reemplaza elementos
.ignoring(NoSuchElementException.class) // Elementos no disponibles aún
.ignoring(ElementClickInterceptedException.class) // Overlays temporales
.withMessage("El menú de navegación no se cargó correctamente");
WebElement menuNavegacion = wait.until(driver -> {
WebElement menu = driver.findElement(By.id("main-navigation"));
return menu.isDisplayed() && menu.isEnabled() ? menu : null;
});
menuNavegacion.findElement(By.linkText("Configuración")).click();
}
Espera con transformación de datos
FluentWait puede transformar datos durante el proceso de espera, útil para validaciones complejas:
@Test
void deberiaEsperarYValidarContenidoJSON() {
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(NoSuchElementException.class);
// Esperar y parsear respuesta JSON mostrada en la página
Map<String, Object> datosRespuesta = wait.until(driver -> {
try {
WebElement jsonElement = driver.findElement(By.id("api-response"));
String jsonText = jsonElement.getText();
if (jsonText.isEmpty() || jsonText.equals("Loading...")) {
return null;
}
// Simular parsing JSON (en aplicación real usarías Jackson/Gson)
return jsonText.contains("\"status\":\"success\"") ?
Map.of("status", "success", "data", "loaded") : null;
} catch (Exception e) {
return null;
}
});
assertThat(datosRespuesta).containsEntry("status", "success");
}
Optimización por tipo de entorno
FluentWait permite ajustar configuraciones según el entorno de ejecución:
@Test
void deberiaAdaptarseAlEntorno() {
Duration timeout = System.getProperty("test.environment", "local").equals("ci")
? Duration.ofSeconds(60) // CI más lento
: Duration.ofSeconds(30); // Local más rápido
Duration polling = System.getProperty("test.environment", "local").equals("ci")
? Duration.ofSeconds(3)
: Duration.ofSeconds(1);
FluentWait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(timeout)
.pollingEvery(polling)
.ignoring(NoSuchElementException.class, TimeoutException.class);
WebElement resultado = wait.until(ExpectedConditions.elementToBeClickable(
By.id("search-results")
));
assertThat(resultado.isDisplayed()).isTrue();
}
Estos ejemplos demuestran cómo FluentWait proporciona control granular sobre el comportamiento de espera, permitiendo optimizar las pruebas según las características específicas de cada aplicación y entorno de ejecución.
Aprendizajes de esta lección de Selenium
- Comprender qué es FluentWait y cómo se diferencia de WebDriverWait.
- Aprender a configurar FluentWait con parámetros como tiempo de espera, intervalo de polling y manejo de excepciones.
- Aplicar FluentWait para condiciones de espera complejas y personalizadas.
- Implementar ejemplos prácticos que demuestran el control granular del polling y la gestión de excepciones.
- Adaptar FluentWait a diferentes contextos y entornos de ejecución para optimizar pruebas.
Completa este curso de Selenium y certifícate
Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs