Fluent Wait

Avanzado
Selenium
Selenium
Actualizado: 05/09/2025

¡Desbloquea el curso de Selenium completo!

IA
Ejercicios
Certificado
Entrar

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 Plus

Qué 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, ofreciendo una flexibilidad sin precedentes para definir condiciones de espera específicas. FluentWait permite configurar múltiples parámetros simultáneamente, desde el tiempo máximo de espera hasta el intervalo de polling, pasando por las excepciones que deben ser ignoradas durante el proceso.

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 TimeoutException
  • pollingEvery(Duration): define el intervalo entre cada verificación de la condición
  • ignoring(Class<? extends Throwable>): especifica qué excepciones deben ser ignoradas durante las verificaciones
  • withMessage(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.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

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

⭐⭐⭐⭐⭐
4.9/5 valoración