Saltar a contenido

3.8.-Pruebas de funcionamiento del despliegue

3.8. Pruebas de funcionamiento del despliegue

Idea principal

Una instalación no se considera terminada porque un proceso aparezca como iniciado. Una prueba de funcionamiento define qué se comprueba, cuál es el resultado esperado, qué evidencia se recoge y qué se hace cuando el resultado no coincide.

En este punto se verifica la cadena completa preparada en los temas anteriores. La cadena puede empezar en una máquina virtual o en un recurso de nube, y continuar por la red, el servidor web, el servidor de aplicaciones, la aplicación y los datos. Una prueba debe ser pequeña, repetible y suficientemente concreta para localizar el componente que falla.

La relación normativa exclusiva es:

Código Descripción
RA1 Implanta arquitecturas web analizando y aplicando criterios de funcionalidad.
CE f Se han realizado pruebas de funcionamiento de los servidores web y de aplicaciones, y de tecnologías de virtualización en la nube y en contenedores.

Qué deberías saber al terminar

Deberías poder:

  • convertir un requisito en una prueba con resultado esperado;
  • comprobar estado, puertos, HTTP, comunicación interna y persistencia;
  • registrar evidencias e interpretar una incidencia sin cambiar varias cosas a la vez.

Mapa del tema

Definiremos una prueba, seguiremos capas desde el entorno hasta la aplicación, consultaremos evidencias y cerraremos con un informe.

1. Qué es una prueba de funcionamiento

Una prueba relaciona una condición inicial, una acción, un resultado esperado y una evidencia. Por ejemplo, si Nginx debe publicar la aplicación en el puerto 80, la acción puede ser solicitar /health y el resultado esperado puede ser una respuesta 200 en menos de un tiempo acordado.

Prueba de funcionamiento

Comprobación planificada que aporta evidencias sobre si un servicio o una cadena de servicios cumple una condición definida en un entorno concreto.

Una evidencia es el dato que demuestra qué ha ocurrido: una captura, la salida de un comando, una respuesta HTTP o una línea de registro. Cuando probamos la cadena de extremo a extremo, comprobamos el recorrido completo desde el cliente hasta la aplicación y los datos, no solo que un proceso esté encendido.

No es suficiente con escribir «funciona». Hay que indicar desde dónde se lanza la prueba, qué versión se está utilizando y qué respuesta se considera correcta. Una prueba puede ser manual durante el aprendizaje, pero debe poder repetirse.

1.1. Del requisito al caso de prueba

El punto de partida no es el comando, sino el requisito. Si el requisito es «la aplicación debe estar disponible a través de Nginx», hay que convertirlo en una condición que se pueda observar. Un caso de prueba completo responde, como mínimo, a estas preguntas:

Campo Pregunta que responde Ejemplo
Precondiciones ¿Qué debe estar preparado? Servicios iniciados y red creada
Origen ¿Desde dónde se comprueba? Cliente autorizado, no el contenedor
Acción ¿Qué se ejecuta o solicita? curl contra /catalogo/health
Resultado esperado ¿Qué significa que pasa? HTTP 200 y contenido válido
Evidencia ¿Qué se conserva? Orden, hora, respuesta y logs
Limpieza ¿Qué se revierte al terminar? Borrar el dato sintético creado

El resultado esperado debe ser observable y medible. «La página se ve bien» es demasiado ambiguo; «la URL responde con 200, contiene el texto Catálogo y no supera diez segundos» permite que otra persona repita la comprobación. Si un requisito no puede traducirse a una observación, todavía no está suficientemente definido para probarlo.

Un caso concreto

Para comprobar la publicación de una aplicación Java, se puede definir el caso T04 así: con Nginx y Tomcat iniciados, desde el cliente autorizado se solicita en un laboratorio local http://localhost/catalogo/health; se espera HTTP 200, un cuerpo válido y una entrada correspondiente en los registros de Nginx y Tomcat. La prueba no queda cerrada hasta guardar el resultado y la hora.

2. Diseñar una matriz de pruebas

Una matriz es una tabla que relaciona cada comprobación con su resultado esperado y con la evidencia que debemos guardar. Ayuda a no olvidar los niveles del despliegue:

ID Elemento Acción Resultado esperado Evidencia
T01 Instancia o VM Consultar estado y acceso Recurso activo y accesible con la cuenta prevista Panel o comando del proveedor
T02 Contenedor Consultar servicios Contenedores activos y saludables docker compose ps
T03 Red Resolver el servicio interno El nombre y el puerto responden desde la red autorizada curl o nc
T04 Nginx Solicitar la URL pública Código y contenido esperados Respuesta HTTP y navegador
T05 Tomcat Solicitar el contexto de la aplicación Aplicación desplegada y respuesta válida curl y logs
T06 Persistencia Reiniciar el servicio Los datos definidos como persistentes siguen disponibles Comparación antes y después

La matriz no tiene que probarlo todo en un único paso. Primero se comprueban las dependencias más cercanas al fallo y después se realiza una prueba de extremo a extremo.

2.1. Tipos y orden de las pruebas

No todas las comprobaciones tienen el mismo alcance. En un despliegue pequeño conviene avanzar de lo más barato y cercano al fallo a lo más completo:

Tipo Qué comprueba Ejemplo
Humo Que el servicio arranca y responde mínimamente /health devuelve respuesta
Integración Que dos componentes se comunican Nginx alcanza app:8080
Funcional Que una operación produce el resultado esperado Consultar el catálogo
Extremo a extremo Que funciona el recorrido completo Cliente → Nginx → Tomcat → datos
Recuperación Que el servicio vuelve a funcionar tras un cambio Recrear el contenedor y consultar
Negativa Que un fallo controlado se detecta correctamente Backend detenido y 502 esperado

Una prueba negativa no consiste en romper un entorno sin control. Se prepara una condición reversible, se anota el resultado esperado y se restaura el servicio al terminar. Por ejemplo, esperar un 502 al detener Tomcat puede confirmar que Nginx detecta la indisponibilidad del backend, pero no demuestra que la aplicación esté operativa.

3. Comprobar el entorno y los servicios

En una máquina virtual o instancia cloud se comprueban el estado del recurso, el acceso administrativo, la dirección y las reglas del firewall. El firewall es el conjunto de reglas que permite o bloquea comunicaciones. Nunca se debe pegar una clave privada ni un token, que es un valor secreto usado para demostrar que una persona o programa tiene permiso, en el informe.

En un entorno Docker, una primera comprobación puede ser:

docker compose ps
docker compose images
docker compose logs --tail=50 web
docker compose logs --tail=50 app
docker stats --no-stream

El estado running solo indica que el proceso principal no ha terminado. Un healthcheck es una comprobación automática, como solicitar /health, que indica si el servicio responde. Puede añadir una señal útil, pero debe estar bien diseñado y no sustituye a una petición funcional completa.

Para revisar puertos en el anfitrión:

ss -tulpn
docker compose port web 80

docker compose port muestra qué puerto del host está asociado al puerto del servicio. El comando docker port también sirve si se conoce el nombre real del contenedor, pero en Compose ese nombre puede incluir el proyecto y el índice de la réplica. Compara lo observado con la ficha de requisitos. Un puerto abierto no demuestra que la aplicación responda correctamente; solo indica que hay algo escuchando.

3.1. Elegir el origen de la prueba

El lugar desde el que se ejecuta la comprobación forma parte del caso. Desde el propio servidor, localhost prueba la interfaz local; no demuestra que el firewall, el DNS ni la ruta pública permitan el acceso de una persona usuaria. En una instancia cloud conviene separar al menos estos orígenes:

  • Dentro del contenedor: ayuda a comprobar el proceso y su puerto interno.
  • Desde otro servicio de la red interna: comprueba DNS, red y puerto entre servicios.
  • Desde el anfitrión o una red autorizada: comprueba la publicación del puerto y las reglas locales.
  • Desde el cliente previsto: comprueba la dirección pública, el DNS y las reglas de firewall o del grupo de seguridad del proveedor.

Una aplicación que responde en localhost dentro de Tomcat puede seguir siendo inaccesible desde Nginx. Del mismo modo, una aplicación que funciona desde la máquina cloud puede estar bloqueada para el resto de la red. Por eso la matriz debe registrar el origen y no solo la URL.

4. Probar HTTP y la comunicación interna

Desde el cliente autorizado se puede consultar una respuesta con curl:

curl --include --max-time 10 http://localhost/health
curl --include --max-time 10 http://localhost/catalogo/

Anota el código, las cabeceras relevantes, el tiempo aproximado y una muestra del cuerpo que no contenga datos sensibles. Si Nginx hace de proxy, realiza también una prueba desde su red interna hacia el backend:

docker compose exec web getent hosts app
docker compose exec web curl --include --max-time 10 http://app:8080/health

La herramienta getent puede no estar instalada en todas las imágenes. En ese caso usa una imagen de diagnóstico temporal o una utilidad disponible en la red; no instales herramientas permanentes sin documentar el cambio.

getent comprueba la resolución de nombres y curl comprueba además que se puede establecer una comunicación HTTP. Una orden como nc -z solo demuestra que el puerto TCP acepta una conexión; no demuestra que Tomcat haya desplegado la aplicación ni que su respuesta sea correcta. Si el contenedor de diagnóstico no incluye curl, utiliza una imagen que lo incorpore y registra cuál se ha usado.

El flujo de diagnóstico se puede representar así:

flowchart TD
  A["¿La instancia o VM está activa?"] -->|No| I1["Revisar proveedor, acceso y firewall"]
  A -->|Sí| B["¿El contenedor o servicio está activo?"]
  B -->|No| I2["Revisar estado y logs"]
  B -->|Sí| C["¿El puerto y el DNS responden?"]
  C -->|No| I3["Revisar red, publicación y nombres"]
  C -->|Sí| D["¿HTTP devuelve lo esperado?"]
  D -->|No| I4["Revisar Nginx, Tomcat y aplicación"]
  D -->|Sí| E["Registrar evidencia y resultado"]

5. Aplicar las pruebas y conservar evidencias

5.1. Interpretar resultados y registros

Los códigos HTTP ayudan a localizar el problema, aunque no sustituyen a los logs:

  • 2xx: la petición se ha procesado correctamente según el servidor;
  • 3xx: hay una redirección que también debe comprobarse;
  • 4xx: el destino, el recurso o los permisos de la petición no son correctos;
  • 5xx: ha fallado el servidor o un componente intermedio.

Un 502 Bad Gateway suele indicar que Nginx no puede comunicarse con el backend; un 404 Not Found puede indicar una ruta incorrecta o una aplicación no desplegada en el contexto esperado. Un 3xx no es automáticamente un éxito: hay que comprobar la cabecera Location y decidir si la redirección forma parte del comportamiento esperado. Un 4xx puede ser el resultado correcto de una prueba negativa, por ejemplo al comprobar que una ruta protegida rechaza a una persona no autenticada. Revisa los registros de cada componente en el mismo intervalo temporal:

Familias de códigos de estado HTTP
Las familias de códigos HTTP orientan el diagnóstico, pero siempre deben interpretarse junto con la petición y los registros.
docker compose logs --since=10m web
docker compose logs --since=10m app

Para observar el código y el tiempo de una petición sin ocultar una respuesta de error, se puede usar:

curl --silent --show-error --include --max-time 10 \
  --write-out '\nHTTP=%{http_code} TIME=%{time_total}s\n' \
  http://localhost/catalogo/health

No añadas --location sin decidirlo antes: seguir una redirección puede ocultar que la primera respuesta no era la esperada. Guarda la hora, la orden ejecutada, el origen, el resultado y la interpretación. Si una prueba falla, conserva el primer estado fallido antes de realizar cambios.

5.2. Probar persistencia y recuperación básica

Si la aplicación utiliza datos persistentes, crea un dato de prueba no sensible, reinicia el servicio y comprueba que el dato sigue disponible. Distingue entre reiniciar un proceso, recrear un contenedor y eliminar un volumen: no tienen el mismo efecto.

Una comprobación sencilla puede documentarse con esta tabla:

Momento Operación Dato visible Resultado
Inicial Crear registro de prueba Sí Línea base
Cambio Recrear el servicio sin borrar volumen Pendiente Debe mantenerse
Final Consultar de nuevo Pendiente Comparar con la línea base

No uses información personal real para una prueba de aula. Si el dato no persiste, registra si se esperaba que fuera efímero o si existe un defecto de configuración.

5.3. Healthchecks y disponibilidad real

Un healthcheck automatiza una comprobación pequeña y permite que Compose marque un servicio como healthy o unhealthy. No sustituye a la prueba funcional: una ruta de salud puede responder aunque la aplicación no pueda consultar la base de datos o aunque una operación concreta falle.

Un fragmento orientativo es el siguiente:

services:
  app:
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - http://localhost:8080/catalogo/health >/dev/null || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 30s

  web:
    depends_on:
      app:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - http://localhost/catalogo/health >/dev/null || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 10s

Las rutas son ejemplos y deben sustituirse por las que realmente ofrezca la aplicación. Además, la imagen debe contener wget (o la herramienta elegida): si no lo contiene, el healthcheck fallará aunque el servicio funcione. En ese caso prepara una imagen con la utilidad o usa una comprobación externa; no instales paquetes manualmente en un contenedor en ejecución y olvides el cambio. Comprueba el resultado con:

docker compose ps
docker inspect --format '{{json .State.Health}}' "$(docker compose ps -q app)"

La propiedad depends_on con service_healthy ayuda a ordenar el arranque, pero no garantiza que una aplicación permanezca disponible: las peticiones posteriores deben seguir gestionando errores y reintentos.

5.4. Informe de pruebas

El informe mínimo debe incluir entorno, versión, fecha, persona que ejecuta, matriz de pruebas, evidencias, incidencias y conclusión. Cada incidencia debe tener una descripción reproducible:

ID: INC-001
Prueba: T04
Fecha y hora: 2026-11-01 10:30
Resultado esperado: HTTP 200 en /health
Resultado obtenido: HTTP 502
Contexto: Nginx activo; app reiniciada recientemente
Evidencia: extracto de logs y comando curl
Hipótesis: el proxy no resuelve el nombre app
Acción siguiente: comprobar la red compartida y repetir T03
Estado: abierta

Una incidencia cerrada debe explicar la causa, el cambio realizado y la prueba que demuestra la solución. No se debe convertir un informe de pruebas en una lista de cambios sin evidencia.

El informe puede usar cuatro estados para no confundir una prueba pendiente con una prueba fallida:

  • PASS: el resultado observado cumple todo lo esperado.
  • FAIL: la prueba se ha ejecutado y no cumple el resultado esperado.
  • BLOCKED: no se puede ejecutar por una dependencia o permiso ausente.
  • N/A: no se aplica al alcance acordado, con una justificación concreta.

El despliegue se puede considerar verificado cuando las pruebas previstas están en PASS, las incidencias abiertas tienen una decisión explícita y las evidencias permiten repetir las comprobaciones sin revelar secretos.

6. Buenas prácticas

  • Definir el resultado antes de probar: evita aceptar cualquier respuesta como correcta.
  • Probar de dentro hacia fuera: empieza por proceso, red y puerto, y termina con el recorrido completo desde el cliente.
  • Aislar cambios: modifica una condición cada vez y repite la prueba que falló.
  • Conservar evidencias reproducibles: anota comandos, versiones, horas y resultados sin incluir secretos.
  • Probar recuperación: reinicia o recrea los servicios según el escenario y comprueba la persistencia esperada.

7. Errores frecuentes

Error frecuente Por qué ocurre Cómo evitarlo
Confundir proceso activo con servicio funcional Solo se mira running Haz una petición funcional y revisa su respuesta
Probar únicamente desde el propio servidor Se evita la red real del cliente Prueba desde el origen autorizado y desde la red interna
Cambiar varias configuraciones a la vez Se intenta resolver rápido Conserva el primer fallo y modifica una variable cada vez
Guardar capturas sin contexto No se sabe versión, hora o comando Añade identificador, entorno y resultado esperado
Probar con datos reales Se busca una evidencia rápida Usa datos sintéticos y elimina el entorno al terminar

8. Resumen

En este tema has aprendido que:

  • una prueba debe tener acción, resultado esperado y evidencia;
  • el despliegue se comprueba por capas: entorno, proceso, red, HTTP, aplicación y persistencia;
  • los códigos, puertos y logs son evidencias distintas que deben interpretarse juntas;
  • un informe de incidencias permite repetir el diagnóstico y verificar la solución.

Idea clave

La pregunta «¿funciona?» solo tiene valor técnico cuando se concreta en una condición que otra persona puede repetir y comprobar.

9. Para seguir practicando

Bibliografía y fuentes

Presentación

DAW-U3.8 · Pruebas de funcionamiento del despliegue