Por Qué Importa el Testing en Tiempo Real

Las aplicaciones web modernas dependen cada vez más de funcionalidades en tiempo real. Aplicaciones de chat, dashboards en vivo, tickers de bolsa, herramientas de edición colaborativa, sistemas de notificaciones y juegos multijugador dependen de conexiones persistentes entre cliente y servidor. Probar estas funcionalidades requiere entender los protocolos subyacentes y los desafíos únicos que presentan.

A diferencia de los ciclos tradicionales de request-response HTTP, la comunicación en tiempo real es bidireccional y continua. Esta diferencia fundamental implica que tu enfoque de testing debe adaptarse.

Entendiendo el Protocolo WebSocket

HTTP vs WebSocket

El HTTP tradicional sigue un modelo request-response: el cliente envía una solicitud, el servidor responde y la conexión se cierra (o permanece inactiva en HTTP/1.1 keep-alive). Si el servidor tiene datos nuevos, no puede enviarlos al cliente — el cliente debe solicitarlos.

WebSocket resuelve esto estableciendo una conexión persistente y full-duplex:

sequenceDiagram participant Client as Cliente participant Server as Servidor Note over Client,Server: HTTP Upgrade Handshake Client->>Server: GET /chat (Upgrade: websocket) Server->>Client: 101 Switching Protocols Note over Client,Server: Conexión WebSocket Establecida Client->>Server: {"type": "message", "text": "Hola"} Server->>Client: {"type": "message", "text": "¡Hola!"} Server->>Client: {"type": "notification", "count": 3} Client->>Server: {"type": "typing", "user": "alice"} Note over Client,Server: Cualquier lado puede enviar en cualquier momento

El Handshake de WebSocket

Toda conexión WebSocket comienza con una solicitud HTTP upgrade:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

El servidor responde con:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Después de este handshake, la conexión cambia de HTTP al protocolo WebSocket. A partir de este punto, los datos fluyen como frames en ambas direcciones.

Otras Tecnologías de Tiempo Real

WebSocket no es la única opción para comunicación en tiempo real:

TecnologíaDirecciónCaso de Uso
WebSocketBidireccionalChat, gaming, edición colaborativa
Server-Sent Events (SSE)Servidor a clienteFeeds de noticias, notificaciones, dashboards
Long PollingBidireccional simuladoSistemas legacy, opción de fallback
HTTP/2 Server PushServidor a clientePrecarga de assets (no datos generales)

Inspección de Tráfico WebSocket

Usando Chrome DevTools

  1. Abre DevTools (F12) y ve a la pestaña Network
  2. Haz clic en el filtro WS para mostrar solo conexiones WebSocket
  3. Haz clic en una conexión WebSocket para ver detalles
  4. La pestaña Messages muestra todos los frames enviados y recibidos
  5. Las flechas verdes indican frames salientes (cliente a servidor)
  6. Las flechas rojas/blancas indican frames entrantes (servidor a cliente)

Aspectos clave a inspeccionar:

  • Headers del handshake — Verifica tokens de autenticación correctos
  • Contenido de frames — Verifica que la estructura JSON coincida con el schema esperado
  • Timing de frames — Mide la latencia entre mensajes enviados y recibidos
  • Estado de conexión — Monitorea cierres inesperados

Usando wscat para Testing en Línea de Comandos

wscat es un cliente WebSocket para terminal:

# Instalar
npm install -g wscat

# Conectar a un servidor WebSocket
wscat -c wss://echo.websocket.org

# Enviar un mensaje
> {"type": "ping"}

# Recibir respuesta
< {"type": "pong"}

Esto es útil para probar endpoints WebSocket independientemente de la UI.

Qué Probar en Funcionalidades de Tiempo Real

Ciclo de Vida de la Conexión

FaseQué Probar
ConexiónHandshake exitoso, autenticación durante el upgrade
ActivaEntrega de mensajes, orden, latencia
InactivaMecanismo de keep-alive heartbeat/ping-pong
InterrupciónReconexión ante pérdida de red, recuperación de datos
CierreCierre limpio (código 1000), manejo de cierre anormal

Entrega de Mensajes

Verifica que los mensajes sean:

  • Entregados — Cada mensaje enviado llega al destinatario
  • Ordenados — Los mensajes llegan en la secuencia correcta
  • Completos — Sin truncamiento de mensajes grandes
  • Oportunos — Entrega dentro de latencia aceptable (típicamente <500ms para chat)

Lógica de Reconexión

Cuando la conexión se cae (cambio de red, reinicio del servidor, timeout):

  1. ¿El cliente detecta la desconexión?
  2. ¿Intenta reconexión automática?
  3. ¿Hay backoff exponencial para evitar sobrecargar el servidor?
  4. ¿La UI informa al usuario sobre el estado de la conexión?
  5. ¿Se recuperan los mensajes perdidos después de la reconexión?
  6. ¿Hay prevención de mensajes duplicados?

Conexiones Concurrentes

Prueba escenarios con múltiples usuarios simultáneos:

  • 2 usuarios en la misma sala de chat
  • 10 usuarios editando el mismo documento
  • 100 usuarios en el mismo dashboard en vivo
  • ¿El broadcasting funciona correctamente para todos los clientes conectados?

Ejercicio: Testing de una Aplicación de Chat en Tiempo Real

Estás probando una aplicación de mensajería de equipo similar a Slack. La aplicación usa WebSocket para entrega de mensajes en tiempo real, indicadores de escritura y estado de presencia (online/offline).

Escenarios de Testing a Ejecutar

Escenario 1: Entrega Básica de Mensajes

Abre dos ventanas del navegador con sesiones de diferentes usuarios en el mismo canal.

PasoAcciónResultado Esperado
1Usuario A envía “Hola”El mensaje aparece instantáneamente para el Usuario A
2Revisa la ventana del Usuario B“Hola” del Usuario A aparece en menos de 1 segundo
3Usuario B responde “¡Hola!”El mensaje aparece instantáneamente para el Usuario B
4Revisa la ventana del Usuario A“¡Hola!” del Usuario B aparece en menos de 1 segundo
5Verifica el orden de mensajesAmbos usuarios ven los mensajes en el mismo orden

Escenario 2: Indicador de Escritura

PasoAcciónResultado Esperado
1Usuario A comienza a escribirUsuario B ve “Usuario A está escribiendo…” en menos de 2 segundos
2Usuario A deja de escribir (5s)El indicador de escritura desaparece para el Usuario B
3Usuario A retoma la escrituraEl indicador reaparece para el Usuario B
4Usuario A envía el mensajeEl indicador de escritura se reemplaza por el mensaje

Escenario 3: Interrupción de Conexión

PasoAcciónResultado Esperado
1Usuario A está conectadoOperación normal
2Desactiva la red del Usuario ALa UI muestra “Reconectando…” o indicador similar
3Usuario B envía un mensajeEl mensaje queda en cola para el Usuario A
4Reactiva la red del Usuario AConexión restaurada, mensajes perdidos entregados
5Verifica que no haya duplicadosCada mensaje aparece exactamente una vez

Para simular interrupción de red en Chrome: DevTools > Network > Throttling > Offline.

Escenario 4: Estado de Presencia

PasoAcciónResultado Esperado
1Usuario A está activoUsuario B ve a Usuario A como “Online”
2Usuario A queda inactivo (5 min)El estado cambia a “Ausente” para el Usuario B
3Usuario A cierra el navegadorEl estado cambia a “Offline” para el Usuario B
4Usuario A reabre la aplicaciónEl estado vuelve a “Online”

Inspección de Frames WebSocket

Mientras ejecutas los escenarios anteriores, monitorea el tráfico WebSocket en DevTools:

// Saliente: Usuario envía un mensaje
{"type": "message", "channel": "general", "text": "Hola", "id": "msg_123"}

// Entrante: Servidor confirma
{"type": "ack", "id": "msg_123", "timestamp": 1711234567890}

// Entrante: Mensaje broadcast a otros usuarios
{"type": "message", "channel": "general", "from": "alice", "text": "Hola", "id": "msg_123"}

// Saliente: Indicador de escritura
{"type": "typing", "channel": "general"}

// Entrante: Ping (keep-alive)
{"type": "ping"}

// Saliente: Respuesta Pong
{"type": "pong"}

Verifica que:

  • Cada mensaje saliente recibe una confirmación
  • Los IDs de mensaje son únicos y secuenciales
  • Los timestamps son precisos
  • Los frames ping/pong mantienen la conexión
Solución: Bugs Comunes Encontrados en Testing de Tiempo Real

Bug 1: Orden de mensajes en reconexión Después de reconectarse, los mensajes perdidos pueden llegar desordenados. La solución es usar secuenciamiento del lado del servidor y reordenamiento del lado del cliente.

Bug 2: Indicador de escritura atascado Si el usuario navega a otra página mientras escribe, el indicador permanece visible para otros. La solución es limpiar el estado de escritura en eventos de navegación/blur.

Bug 3: Estado de presencia obsoleto después de crash Si el navegador se cierra abruptamente, el servidor nunca recibe una desconexión limpia. La solución es un timeout de heartbeat del lado del servidor (ej: marcar offline después de 30 segundos sin ping).

Bug 4: Mensajes duplicados en conexiones inestables Si el cliente reenvía un mensaje antes de recibir confirmación, aparecen duplicados. La solución son claves de idempotencia — el servidor rechaza mensajes con IDs duplicados.

Bug 5: Memory leak por listeners de WebSocket Las conexiones de larga duración acumulan event listeners si no se limpian correctamente, causando degradación de rendimiento. Monitorea el uso de memoria del navegador durante sesiones prolongadas.

Testing de Server-Sent Events

Para aplicaciones que usan SSE en lugar de WebSocket, el enfoque de testing difiere ligeramente:

// SSE crea una conexión unidireccional
const eventSource = new EventSource('/api/notifications');

eventSource.onmessage = (event) => {
  console.log('Notificación:', event.data);
};

Las conexiones SSE aparecen en DevTools Network como tipo EventStream. Diferencias clave en testing:

  • Solo servidor a cliente — verifica que el cliente no pueda enviar datos por la misma conexión
  • Reconexión automática — SSE tiene reconexión incorporada con header Last-Event-ID
  • Prueba el campo retry — el servidor puede especificar el delay de reconexión en milisegundos

Consideraciones de Rendimiento

Al probar funcionalidades en tiempo real, presta atención a:

  1. Uso de memoria a lo largo del tiempo — Conexiones WebSocket que corren por horas no deben tener memory leaks
  2. Uso de CPU durante alto volumen de mensajes — Prueba con ráfagas rápidas (100 mensajes/segundo)
  3. Impacto en batería en móvil — Las conexiones persistentes afectan la vida de la batería
  4. Uso de ancho de banda — Mide el tamaño de los frames, especialmente para datos binarios
  5. Conexiones concurrentes máximas — La mayoría de navegadores limitan conexiones WebSocket por dominio (típicamente 6-30)

Puntos Clave

  • WebSocket proporciona comunicación persistente y bidireccional fundamentalmente diferente del request-response HTTP
  • Siempre prueba el ciclo de vida completo de la conexión: handshake, comunicación activa, interrupción y cierre
  • La lógica de reconexión es una de las áreas con más bugs en aplicaciones de tiempo real
  • Usa el filtro WS en DevTools y wscat para inspeccionar frames WebSocket directamente
  • Prueba con múltiples usuarios simultáneos para detectar problemas de broadcasting y orden
  • Monitorea métricas de rendimiento durante sesiones WebSocket prolongadas para detectar memory leaks