Pruebas de humo (Smoke Tests) y por qué los agentes no dejan de escribirlas
Smoke tests explicados: qué comprobar, dónde ejecutarlos, qué excluir y por qué los agentes de código los añaden a CI y a los despliegues.
Una prueba de humo es un conjunto reducido de verificaciones que comprueban que un sistema desplegado está fundamentalmente vivo: el proceso arrancó, la página principal devuelve 200, un usuario puede iniciar sesión y la base de datos responde a una consulta. No juzga si el software es correcto; decide si ejecutar el resto de la batería de pruebas vale el tiempo invertido.
Si llevas años desplegando a CI sin haber necesitado nunca esa definición, no eres el único. La expresión suele aparecer sin presentación previa, y últimamente aparece dentro de un pull request: un smoke.sh o un smoke.spec.ts que un agente de programación añadió mientras terminaba otra cosa.
Este artículo cubre qué debe incluir una prueba de humo, dónde se ejecuta, cómo se ve una mínima en código, el filtro para decidir qué dejar fuera y por qué los agentes las producen con tanta fiabilidad.
Puntos clave
- Una prueba de humo verifica que un sistema desplegado está vivo (arranque, 200 en la página principal, login, una lectura real de base de datos) y tarda segundos, no minutos.
- Se ejecuta dos veces: como primera barrera en CI y justo después de un despliegue contra el entorno al que realmente se desplegó; una ejecución contra localhost no puede detectar fallos de despliegue.
- Una verificación pertenece a la suite de humo solo si su fallo bloquea a todos los usuarios, todos los usuarios pasan por ella y puede romperse durante el despliegue. Si no cumple las tres condiciones, va a regresión.
- Los agentes de programación escriben pruebas de humo porque una tarea terminada necesita una señal barata, binaria y rápida de que nada fundamental se rompió, que es exactamente lo que produce una prueba de humo.
- Establece un techo estricto para la suite y mueve todo lo que lo supere a regresión; una suite de humo de doce minutos es una suite de regresión con el nombre equivocado.
¿Qué es una prueba de humo?
Una prueba de humo responde a una sola pregunta, «¿está esta build lo bastante viva como para seguir probándola?», y su nombre suele atribuirse a la práctica de encender hardware nuevo y vigilar si sale humo. En software la forma es la misma: un recorrido rápido y superficial por las rutas de las que depende cada usuario, con un resultado binario y sin opinión sobre la corrección.
Se sitúa fuera de la pirámide de testing habitual, más que en una de sus capas; las capas en sí se tratan en Integration Tests vs End-to-End Tests y Unit vs Integration Testing in JavaScript: What to Use When. Una prueba de humo es una barrera situada delante de esas suites, no un miembro de ellas.
¿Dónde se ejecuta el smoke testing?
Las pruebas de humo se ejecutan en dos lugares: como primera barrera en CI antes de que arranquen las suites más largas, y justo después de un despliegue, contra el entorno al que realmente se desplegó. La segunda ubicación es la que justifica su existencia, y es la que más a menudo se omite.
Ejecutar una prueba de humo contra localhost anula su propósito, porque los fallos que existe para detectar solo ocurren en el despliegue: una variable de entorno ausente, una migración que nunca se ejecutó, un bundle de assets que nunca se publicó. Un proceso arrancado en el runner de CI con APP_URL=localhost y una base de datos nueva en memoria no tiene disponible ninguno de esos modos de fallo. Ese tipo de ejecución es una comprobación de arranque, y las comprobaciones de arranque son útiles, pero son algo distinto y más débil. Una ejecución local contra servicios simulados no puede fallar por ninguna de las razones por las que falla un despliegue, así que no debería llevar ese nombre.
La ejecución posterior al despliegue es también el disparador natural para el rollback: AWS CodeDeploy ejecuta tu función de validación una vez que la nueva versión está sirviendo tráfico de prueba, y un resultado fallido dispara un rollback. Ten presentes los límites de esa señal, eso sí. Una prueba de humo post-despliegue en verde demuestra que el sistema respondió, no que el recorrido del usuario funcione; revisar session replays de las primeras sesiones reales tras una release es la técnica que distingue ambas cosas, porque un botón de checkout que lanza un error por un hash de chunk cambiado nunca aparece en un código de estado.
¿Cómo se ve una prueba de humo?
Una suite de humo completa puede ser un único script corto que golpea el destino desplegado real sin mocks: una espera acotada al endpoint de salud, una petición autenticada y una lectura que atraviesa la aplicación hasta la base de datos.
#!/usr/bin/env bash
# smoke.sh: runs against the deployed target in $APP_URL, never localhost
set -euo pipefail
: "${APP_URL:?set APP_URL to the deployed base URL}"
: "${SMOKE_USER:?}" "${SMOKE_PASS:?}"
status() { curl --silent --output /dev/null --write-out '%{http_code}' "$@"; }
# 1. Wait for the process to come up. This absorbs container start-up, nothing else.
for _ in $(seq 1 "${SMOKE_RETRIES:-10}"); do
[ "$(status "$APP_URL/health")" = "200" ] && break
sleep 3
done
[ "$(status "$APP_URL/health")" = "200" ] || { echo "health: not 200"; exit 1; }
# 2. Login. Assert the one status your app returns (200 for a JSON API, 302 for a form post).
code=$(status --data-urlencode "email=$SMOKE_USER" \
--data-urlencode "password=$SMOKE_PASS" "$APP_URL/login")
[ "$code" = "200" ] || { echo "login: got $code, expected 200"; exit 1; }
# 3. A real read through the app, with the credentials the app was deployed with.
body=$(curl --silent --fail "$APP_URL/api/products?limit=1") || { echo "query: request failed"; exit 1; }
[ -n "$body" ] || { echo "query: empty body"; exit 1; }
echo "smoke: ok"
El helper status usa el --write-out '%{http_code}' de curl para capturar el código de respuesta, mientras que --output /dev/null descarta el cuerpo. set -euo pipefail hace que el script termine al primer fallo. El bucle de reintentos existe únicamente para absorber el tiempo de arranque tras un despliegue; no es una forma de disimular una verificación inestable.
Cada aserción nombra un estado exacto. Todos los códigos de la RFC 9110 tienen un significado, así que una verificación que acepta «cualquier respuesta» no es una verificación: un 404 de una ruta que debería existir es un fallo de despliegue, y un 302 solo es aceptable donde el contrato sea una redirección. La tercera verificación importa más de lo que parece. Hacer ping al servidor de base de datos con una herramienta como pg_isready confirma que el servidor acepta conexiones; una lectura a través de la aplicación confirma que la app puede alcanzar la base de datos con la cadena de conexión, las credenciales y el esquema con los que fue desplegada, que es justamente la clase de fallo para la que existen las pruebas de humo.
Qué no pertenece a una prueba de humo
Los casos límite, la lógica de negocio, cualquier cosa lenta y cualquier cosa inestable no pertenecen a una prueba de humo. Una verificación pertenece a la suite de humo solo si se cumplen las tres condiciones: su fallo impide a todos los usuarios hacer cualquier cosa, todos los usuarios pasan por ella y puede romperse durante un despliegue. Una verificación que cumple menos de tres pertenece a la suite de regresión. Ese planteamiento de tres preguntas aparece en la guía de al menos un proveedor de testing en CI, y es una heurística más que un estándar.
| Verificación candidata | ¿Bloquea a todos los usuarios? | ¿Todos los usuarios pasan por ella? | ¿Se rompe al desplegar? | Veredicto |
|---|---|---|---|---|
| El endpoint de salud devuelve 200 | Sí | Sí | Sí | Humo |
| Login con una cuenta de prueba | Sí | Sí | Sí | Humo |
| Un código de cupón aplica un descuento | No | No | Sí | Regresión |
| La exportación CSV de admin se descarga | No | No | Sí | Regresión |
| Llega el email de restablecimiento de contraseña | No | No | Sí | Regresión |
La inestabilidad (flakiness) descalifica por sí sola. Una verificación de humo que falla de forma aleatoria enseña al equipo a reejecutar barreras en rojo, y una barrera que la gente reejecuta hasta que pasa ya no es una barrera.
¿Por qué los agentes de programación escriben pruebas de humo constantemente?
Los agentes de programación escriben pruebas de humo porque un agente que termina una tarea necesita una señal barata, rápida e inequívoca de que no ha roto el sistema entero, y esa es exactamente la señal que produce una prueba de humo. Un agente que acaba de editar código no puede permitirse la suite completa en cada iteración ni puede juzgar la corrección por inspección, así que recurre a la verificación que responde «¿sigue vivo?» en segundos y devuelve un código de salida limpio.
Esto no es accidental. La documentación de Claude Code de Anthropic indica a los desarrolladores que entreguen al agente algo que pueda ejecutar para comprobar su propio trabajo, ya sea una suite de pruebas, una build, un linter o un pequeño script. Con una señal que puede leer por sí mismo, el agente sigue trabajando y reverificando sin esperar a que una persona detecte el error. Un script de humo encaja con esa descripción de forma muy ajustada, y por eso los repositorios escritos por agentes tienden a generar uno incluso cuando el equipo nunca usó el término. Esa es la razón por la que los desarrolladores se están encontrando ahora con «smoke test», a menudo al descubrir uno en un diff que no escribieron.
Cuando aparece uno en un PR, revísalo con cuatro preguntas. ¿Lee la URL de destino desde una variable de entorno en lugar de codificar localhost? ¿Comprueba un estado específico en lugar de «que no sea un error»? ¿Termina en segundos? ¿Cada verificación pasa el filtro de tres preguntas anterior? Una prueba de humo escrita por un agente que falle alguna de estas es o bien una comprobación de arranque, o bien una prueba de regresión con la etiqueta equivocada.
El modo de fallo: la suite crece
Una suite de humo deja de ser una barrera en el momento en que supera unos pocos segundos. El patrón es predecible: cada funcionalidad añade una verificación «por si acaso», un agente añade otra después de cada tarea, y un día la barrera tarda doce minutos y la gente empieza a saltársela. En ese punto es una suite de regresión lenta con el nombre equivocado.
La solución es un techo estricto y mover a regresión todo lo que lo supere. Nuestro valor por defecto recomendado es un puñado de verificaciones, del orden de cinco, que terminen en segundos; TestingXperts sitúa el límite exterior en diez minutos, pasados los cuales los equipos empiezan a saltarse la barrera. El número exacto importa menos que tener uno escrito y hacerlo cumplir en la revisión, incluida la revisión de las adiciones escritas por agentes.
Conclusión
Una prueba de humo es la prueba más pequeña posible de que un despliegue está vivo: salud, login, una lectura real, ejecutada contra el entorno al que realmente desplegaste, terminada en segundos. Todo lo demás es regresión. La próxima vez que un agente te entregue un smoke.sh, comprueba que apunta a una URL real, que verifica estados exactos y que se mantiene por debajo del techo, y luego conéctalo para que se ejecute después de cada despliegue.
Preguntas frecuentes
¿Cuál es la diferencia entre una prueba de humo y un health check?
Un health check es un endpoint que un orquestador o un balanceador de carga consulta periódicamente para decidir si enruta tráfico o reinicia un contenedor; Kubernetes los llama liveness y readiness probes. Una prueba de humo se ejecuta una vez por despliegue, llama a ese endpoint más un login y una lectura de base de datos, y devuelve un código de salida que controla el pipeline. El endpoint de salud es la primera aserción de la prueba de humo, no un sustituto de ella.
¿Cuál es la diferencia entre smoke testing y sanity testing?
El smoke testing es amplio y superficial: comprueba que las rutas principales de una build están vivas antes de que empiecen pruebas más profundas. El sanity testing, en la terminología convencional de QA, es estrecho y profundo: verifica que un arreglo o cambio concreto funciona sobre una build que ya ha pasado el smoke, y a menudo se considera un subconjunto de las pruebas de regresión. En un pipeline de CI la suite de humo es la barrera; las comprobaciones de sanity van con regresión.
¿Deberían ejecutarse las pruebas de humo contra producción, y es seguro?
Sí. La ejecución posterior al despliegue debe apuntar al entorno al que los usuarios realmente llegan, incluido producción, porque los fallos de despliegue solo aparecen allí. Mantenla segura usando una cuenta de prueba dedicada y precargada, suministrada mediante secretos de CI, limitando las verificaciones a un login y a peticiones de solo lectura, y excluyendo cualquier cosa que escriba datos o envíe correo. Si una escritura es inevitable, acótala a un tenant de prueba y límpiala en el mismo script.
¿Puedo escribir una prueba de humo en Playwright o Cypress en lugar de un script de shell?
Sí, siempre que siga las mismas reglas: leer la URL base desde una variable de entorno, verificar estados exactos o elementos visibles, y terminar en segundos. Los runners de navegador añaden tiempo de arranque y de carga de página por cada verificación, así que limita la suite de humo en navegador a uno o dos recorridos y deja las verificaciones HTTP en curl. Coloca el spec de humo en su propio archivo para que CI pueda ejecutarlo sin el resto de la suite.