Ejecutando Tests de Postman con CI/CD
Buscando un framework para realizar pruebas de integración, descubrí que nuestros amigos de Postman implementaron una forma muy interesante de probar tu API. En toda colección de Postman, hay una sección llamada Tests donde podés declarar todas las validaciones que quieras hacer sobre la respuesta.
En el ejemplo oficial anterior, están probando un escenario en el que obtienen todos los items, luego crean un nuevo y finalmente verifican si el elemento fue creado como se esperaba. Eso es genial, pero ¿cómo podemos ejecutar estas pruebas desde la consola, para que podamos agregarlo como un paso en nuestro pipeline de CI/CD? Aquí es donde entra en juego otra gran herramienta del equipo de Postman: Newman.
newman run examples/sample-collection.json
Eso es todo, de esta manera podemos ejecutar cualquier colección de Postman (previamente exportada como un archivo JSON). Parece que encontramos una buena solución para nuestro requisito, pero el mundo real no es tan simple. Probablemente, la API que deseas probar dependa de una base de datos, o peor aún, de APIs externas. Necesitamos descubrir cómo podemos manejar esos escenarios.
¡Docker al rescate!
Gracias a Docker y Docker Compose, podemos ejecutar nuestra API y sus dependencias todas juntas. No estoy escribiendo este post para explicar cómo funciona Docker Compose (hay muchos artículos excelentes sobre eso), así que para simplificar el ejemplo, voy a asumir que nuestra API no tiene dependencias. Solo necesitaríamos los servicios de API y Newman.
version: '3'
services:
cicd-postman-tests-api:
container_name: cicd-postman-tests-api
image: vad1mo/hello-world-rest
cicd-postman-tests-newman:
container_name: cicd-postman-tests-newman
image: postman/newman
entrypoint: sh
command: /src/newman-wrapper.sh
volumes:
- ./src:/src
depends_on:
- cicd-postman-tests-api
Explico la configuración anterior:
- cicd-postman-tests-api es el servicio de la API en sí. Para reducir la cantidad de código adicional que no es relevante para este tutorial, usé la imagen hello-world-rest, que contiene una API muy simple para interactuar.
- cicd-postman-tests-newman es el servicio que ejecuta las pruebas, y utiliza la imagen oficial de Newman del equipo de Postman. Como tenemos que esperar hasta que la API esté lista para recibir solicitudes, utilizamos un script como wrapper para esperar. Tené en cuenta que no es suficiente usar la opción
depends-on
de Docker Compose, ya que esta característica ignora el tiempo de inicio de tu servicio.
Acá está el script wrapper:
#!/bin/sh
set -eu pipefail
echo "Attempting to connect to cicd-postman-tests-api"
until $(nc -zv cicd-postman-tests-api 5050); do
printf '.'
sleep 5
done
echo "Connected to cicd-postman-tests-api!"
newman run /src/postman-collection.json
exit 0
Intentamos conectarnos al servicio que se ejecuta en el puerto 5050
, y esperamos 5 segundos antes de intentarlo de nuevo. Finalmente, cuando la conexión es exitosa, ejecutamos las pruebas de nuestra colección utilizando el binario de Newman.
¡Listo! Ahora podemos ejecutar las pruebas tan fácil como:
docker-compose up --exit-code-from cicd-postman-tests-newman
Usamos la opción --exit-code-from
para especificar que después de que el contenedor cicd-postman-tests-newman se detenga, todos los demás contenedores también deben detenerse, y el código de salida del comando será el que devuelva el contenedor de Newman. De esta manera, forzamos a que el pipeline de CI/CD falle si alguno de los tests falla.
Ahora ¿qué pasa si mi API tiene dependencias? Bueno, simplemente podés agregar esas dependencias (bases de datos, servidores mock, etc.) como services
en el docker-compose.yml, esa es la razón principal por la que introducimos Docker en el stack. Podés ajustar el script newman-wrapper.sh para que también espere por esos servicios.
Conclusión
Gracias a Postman, Newman y Docker, podemos construir y mantener pruebas de integración que pueden ser ejecutadas tanto en pipelines de CI/CD como en entornos locales, permitiendo a los desarrolladores probar el servicio completo en su propio espacio controlado, de manera más rápida y sencilla.