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 PlusLogging: acceso a logs de consola con BiDi
La BiDi API (Bidirectional API) representa una evolución significativa en la arquitectura de Selenium WebDriver, introduciendo un protocolo de comunicación bidireccional entre el cliente y el navegador. A diferencia del protocolo tradicional basado en HTTP, BiDi permite que tanto el cliente como el navegador inicien comunicaciones, habilitando funcionalidades avanzadas como la monitorización en tiempo real de eventos del navegador.
Esta arquitectura bidireccional resulta especialmente valiosa para acceder a logs de consola, ya que permite recibir eventos de logging de forma asíncrona sin necesidad de realizar consultas periódicas al navegador. Los logs de consola incluyen mensajes generados por JavaScript, errores, advertencias y otra información de diagnóstico que resulta crucial para la depuración y el análisis de aplicaciones web.
Configuración inicial para BiDi
Para utilizar la funcionalidad de logging con BiDi, es necesario configurar el driver con las capacidades adecuadas. El navegador debe soportar el protocolo WebDriver BiDi, siendo Chrome y Firefox los navegadores que ofrecen mejor compatibilidad actualmente.
@Test
void configurarDriverParaBiDi() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
WebDriver driver = new ChromeDriver(options);
// El driver está ahora configurado para BiDi
driver.get("https://ejemplo.com");
driver.quit();
}
La configuración establece la conexión WebSocket necesaria para la comunicación bidireccional, permitiendo que el navegador envíe eventos de logging de forma proactiva al cliente de Selenium.
Acceso a logs de consola con LogInspector
El LogInspector es la interfaz principal para trabajar con logs de consola en BiDi. Esta clase proporciona métodos para suscribirse a diferentes tipos de eventos de logging y procesar los mensajes de forma asíncrona.
@Test
void capturarLogsDeConsola() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
LogInspector logInspector = new LogInspector(driver);
// Lista para almacenar los logs capturados
List<ConsoleLogEntry> consoleLogs = new ArrayList<>();
// Suscribirse a logs de consola
logInspector.onConsoleEntry(consoleLogs::add);
// Navegar a una página que genere logs
driver.get("data:text/html,<script>console.log('Mensaje de prueba');</script>");
// Verificar que se capturó el log
assertThat(consoleLogs)
.isNotEmpty()
.extracting(ConsoleLogEntry::getText)
.contains("Mensaje de prueba");
}
}
Filtrado de logs por nivel
Los logs de consola se generan con diferentes niveles de severidad, desde información general hasta errores críticos. BiDi permite filtrar estos logs según su nivel, facilitando el enfoque en los mensajes más relevantes para cada escenario de prueba.
@Test
void filtrarLogsPorNivel() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
LogInspector logInspector = new LogInspector(driver);
List<ConsoleLogEntry> errorLogs = new ArrayList<>();
List<ConsoleLogEntry> warningLogs = new ArrayList<>();
// Filtrar solo errores
logInspector.onConsoleEntry(entry -> {
if (entry.getLevel() == Level.SEVERE) {
errorLogs.add(entry);
} else if (entry.getLevel() == Level.WARNING) {
warningLogs.add(entry);
}
});
// Generar diferentes tipos de logs
driver.get("""
data:text/html,
<script>
console.error('Error crítico');
console.warn('Advertencia importante');
console.log('Información general');
</script>
""");
// Verificar filtrado
assertThat(errorLogs).hasSize(1);
assertThat(warningLogs).hasSize(1);
}
}
Procesamiento asíncrono de logs
Una de las principales ventajas de BiDi es la capacidad de procesar logs de forma asíncrona, permitiendo que las pruebas reaccionen inmediatamente a eventos de logging sin bloquear la ejecución del test.
@Test
void procesarLogsAsincrono() throws InterruptedException {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
LogInspector logInspector = new LogInspector(driver);
CountDownLatch latch = new CountDownLatch(3);
// Procesar logs de forma asíncrona
logInspector.onConsoleEntry(entry -> {
System.out.println("Log recibido: " + entry.getText());
latch.countDown();
});
// Ejecutar JavaScript que genera múltiples logs
driver.get("""
data:text/html,
<script>
setTimeout(() => console.log('Log 1'), 100);
setTimeout(() => console.log('Log 2'), 200);
setTimeout(() => console.log('Log 3'), 300);
</script>
""");
// Esperar a que se procesen todos los logs
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
}
Análisis de logs para depuración
Los logs de consola capturados con BiDi proporcionan información valiosa para la depuración de aplicaciones web. Incluyen detalles como el momento exacto del evento, el contexto de ejecución y metadatos adicionales que facilitan el diagnóstico de problemas.
@Test
void analizarDetallesDelLog() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
LogInspector logInspector = new LogInspector(driver);
List<ConsoleLogEntry> detailedLogs = new ArrayList<>();
logInspector.onConsoleEntry(entry -> {
// Capturar detalles completos del log
detailedLogs.add(entry);
// Mostrar información detallada
System.out.printf("""
Timestamp: %s
Nivel: %s
Mensaje: %s
Fuente: %s
""",
entry.getTimestamp(),
entry.getLevel(),
entry.getText(),
entry.getSource()
);
});
driver.get("data:text/html,<script>console.error('Error con contexto');</script>");
// Verificar que se capturaron los detalles
assertThat(detailedLogs)
.hasSize(1)
.first()
.satisfies(entry -> {
assertThat(entry.getTimestamp()).isNotNull();
assertThat(entry.getLevel()).isEqualTo(Level.SEVERE);
assertThat(entry.getText()).contains("Error con contexto");
});
}
}
El acceso a logs de consola mediante BiDi transforma la capacidad de monitorización y depuración en las pruebas automatizadas, proporcionando visibilidad en tiempo real sobre el comportamiento interno de las aplicaciones web y permitiendo una detección más temprana de problemas potenciales.
Interceptar peticiones de red
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
La interceptación de peticiones de red mediante BiDi API permite monitorizar, modificar y controlar el tráfico HTTP entre la aplicación web y los servidores remotos. Esta funcionalidad resulta fundamental para validar comportamientos de red, simular condiciones específicas y verificar que las aplicaciones manejen correctamente las respuestas del servidor.
El NetworkInspector proporciona la interfaz principal para trabajar con eventos de red, permitiendo acceder a información detallada sobre requests, responses, y el estado de las conexiones de forma asíncrona.
Configuración del NetworkInspector
Para interceptar peticiones de red, es necesario inicializar el NetworkInspector con las capacidades BiDi habilitadas. Este componente se suscribe automáticamente a los eventos de red del navegador, proporcionando acceso completo al tráfico HTTP.
@Test
void configurarInterceptorDeRed() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
// Lista para almacenar peticiones interceptadas
List<HttpRequest> requests = new ArrayList<>();
List<HttpResponse> responses = new ArrayList<>();
// Suscribirse a eventos de red
networkInspector.onRequestSent(requests::add);
networkInspector.onResponseReceived(responses::add);
// Navegar a una página que genere tráfico de red
driver.get("https://httpbin.org/json");
// Verificar que se interceptaron las peticiones
assertThat(requests).isNotEmpty();
assertThat(responses).isNotEmpty();
}
}
Monitorización de peticiones HTTP
La monitorización de peticiones permite examinar todos los aspectos de las comunicaciones HTTP, incluyendo métodos, headers, URLs y payloads. Esta información resulta crucial para verificar que la aplicación realiza las peticiones esperadas con los parámetros correctos.
@Test
void monitorizarPeticionesHTTP() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
List<HttpRequest> apiRequests = new ArrayList<>();
// Filtrar solo peticiones a APIs
networkInspector.onRequestSent(request -> {
String url = request.getUrl();
if (url.contains("/api/") || url.contains("httpbin.org")) {
apiRequests.add(request);
// Mostrar detalles de la petición
System.out.printf("""
Método: %s
URL: %s
Headers: %s
""",
request.getMethod(),
request.getUrl(),
request.getHeaders()
);
}
});
// Ejecutar JavaScript que realiza peticiones AJAX
driver.get("data:text/html,<script>fetch('https://httpbin.org/get?test=123');</script>");
// Verificar características de la petición
assertThat(apiRequests)
.hasSize(1)
.first()
.satisfies(request -> {
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getUrl()).contains("test=123");
});
}
}
Análisis de respuestas HTTP
El análisis de respuestas HTTP proporciona acceso completo a los datos devueltos por el servidor, incluyendo códigos de estado, headers de respuesta y contenido del body. Esta información permite validar que la aplicación recibe y procesa correctamente las respuestas del servidor.
@Test
void analizarRespuestasHTTP() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
List<HttpResponse> successResponses = new ArrayList<>();
List<HttpResponse> errorResponses = new ArrayList<>();
// Clasificar respuestas por código de estado
networkInspector.onResponseReceived(response -> {
int statusCode = response.getStatusCode();
if (statusCode >= 200 && statusCode < 300) {
successResponses.add(response);
} else if (statusCode >= 400) {
errorResponses.add(response);
}
// Log detallado de la respuesta
System.out.printf("""
Status: %d
Content-Type: %s
Response Time: %d ms
""",
response.getStatusCode(),
response.getHeaders().get("content-type"),
response.getTimestamp() - response.getRequest().getTimestamp()
);
});
driver.get("https://httpbin.org/status/404");
// Verificar clasificación de respuestas
assertThat(errorResponses)
.hasSize(1)
.first()
.satisfies(response -> {
assertThat(response.getStatusCode()).isEqualTo(404);
});
}
}
Interceptación y modificación de peticiones
Una funcionalidad avanzada de BiDi es la capacidad de modificar peticiones en tiempo real antes de que alcancen el servidor. Esto permite simular diferentes escenarios, añadir headers de autenticación o modificar parámetros de consulta.
@Test
void modificarPeticionesEnTiempoReal() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
// Interceptar y modificar peticiones
networkInspector.onRequestWillBeSent((request, continueWith) -> {
// Añadir header de autenticación
Map<String, String> modifiedHeaders = new HashMap<>(request.getHeaders());
modifiedHeaders.put("Authorization", "Bearer test-token");
modifiedHeaders.put("X-Custom-Header", "Modified-Value");
// Continuar con la petición modificada
continueWith.with(request.toBuilder()
.setHeaders(modifiedHeaders)
.build());
});
List<HttpRequest> modifiedRequests = new ArrayList<>();
networkInspector.onRequestSent(modifiedRequests::add);
driver.get("https://httpbin.org/headers");
// Verificar que se añadieron los headers
assertThat(modifiedRequests)
.hasSize(1)
.first()
.satisfies(request -> {
assertThat(request.getHeaders())
.containsKey("Authorization")
.containsKey("X-Custom-Header");
});
}
}
Simulación de fallos de red
La simulación de fallos de red permite probar cómo la aplicación maneja condiciones adversas como timeouts, errores de conectividad o respuestas malformadas. BiDi facilita la creación de estos escenarios de prueba sin necesidad de herramientas externas.
@Test
void simularFallosDeRed() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
List<String> failedRequests = new ArrayList<>();
// Interceptar peticiones específicas y simular fallos
networkInspector.onRequestWillBeSent((request, continueWith) -> {
String url = request.getUrl();
if (url.contains("/api/data")) {
// Simular error de red
failedRequests.add(url);
continueWith.withError(NetworkError.CONNECTION_REFUSED);
} else {
// Permitir otras peticiones
continueWith.proceed();
}
});
// Ejecutar JavaScript que maneja errores de red
driver.get("""
data:text/html,
<script>
fetch('/api/data')
.catch(error => console.error('Network error:', error));
</script>
""");
// Verificar que se simuló el fallo
assertThat(failedRequests).contains("/api/data");
}
}
Validación de performance de red
La interceptación de red también permite realizar análisis de performance, midiendo tiempos de respuesta, tamaños de payload y identificando cuellos de botella en las comunicaciones HTTP.
@Test
void validarPerformanceDeRed() {
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
try (WebDriver driver = new ChromeDriver(options)) {
NetworkInspector networkInspector = new NetworkInspector(driver);
Map<String, Long> responseTimes = new ConcurrentHashMap<>();
Map<String, Integer> responseSizes = new ConcurrentHashMap<>();
// Medir métricas de performance
networkInspector.onResponseReceived(response -> {
String url = response.getRequest().getUrl();
long responseTime = response.getTimestamp() - response.getRequest().getTimestamp();
int contentLength = response.getHeaders().containsKey("content-length")
? Integer.parseInt(response.getHeaders().get("content-length"))
: 0;
responseTimes.put(url, responseTime);
responseSizes.put(url, contentLength);
});
driver.get("https://httpbin.org/delay/1");
// Validar métricas de performance
assertThat(responseTimes.values())
.allSatisfy(time -> assertThat(time).isGreaterThan(1000)); // Mínimo 1 segundo por el delay
assertThat(responseSizes.values())
.allSatisfy(size -> assertThat(size).isGreaterThan(0));
}
}
La interceptación de peticiones de red con BiDi API proporciona un control granular sobre las comunicaciones HTTP, permitiendo crear pruebas más robustas que validen tanto el comportamiento funcional como el rendimiento de las aplicaciones web en diferentes condiciones de red.
Aprendizajes de esta lección de Selenium
- Comprender la arquitectura bidireccional de la BiDi API y su ventaja frente al protocolo HTTP tradicional.
- Configurar el driver de Selenium para habilitar la comunicación BiDi mediante WebSocket.
- Capturar, filtrar y procesar logs de consola de forma asíncrona usando LogInspector.
- Interceptar, monitorizar y modificar peticiones y respuestas HTTP con NetworkInspector.
- Simular fallos de red y analizar métricas de rendimiento para pruebas avanzadas de aplicaciones web.
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