Las pruebas de software aumentan la calidad y la confiabilidad de las aplicaciones. Permiten a los desarrolladores encontrar y corregir errores de software, mitigar problemas de seguridad y simular casos de uso de usuarios reales.
Es una parte esencial del desarrollo de cualquier aplicación.
Serverless es una tecnología sorprendente, casi mágica. Las aplicaciones sin servidor, como cualquier otra aplicación, requieren pruebas.
Sin embargo, probar aplicaciones sin servidor difiere de las pruebas tradicionales e introduce nuevos desafíos.
En esta publicación, aprenderá a probar flujos asincrónicos controlados por eventos que pueden o no contener funciones Lambda.
Publicaciones anteriores de la serie:
Parte 1 : aprendió por qué los servicios sin servidor presentan nuevos desafíos de pruebas y mis pautas prácticas para probar servicios sin servidor y funciones de AWS Lambda que mitigan estos desafíos.
Parte 2 : aprendiste a escribir pruebas para tu servicio Serverless. Nos centramos en las funciones Lambda y brindamos consejos y trucos y ejemplos de código escribiendo pruebas para una aplicación Serverless real. Además, aprendiste mi adaptación Serverless a la pirámide de pruebas y la implementaste.
Puede encontrar aquí un proyecto de servicio sin servidor complementario que utiliza las mejores prácticas de pruebas sin servidor .
Tabla de contenido
Pirámide de pruebas sin servidor Re:cap
En la primera publicación de la serie, presenté la pirámide de pruebas sin servidor.
Esta publicación asume que está familiarizado con la pirámide de pruebas y comprende sus principios.
Definimos las siguientes etapas de prueba:
Pruebas unitarias para nuestro código de dominio empresarial de funciones Lambda: pruebe esquemas de validación de entrada y pruebe funciones aisladas.
Pruebas de infraestructura para nuestro código AWS CDK que afirman las mejores prácticas de seguridad.
Pruebas de integración que se ejecutan después de la implementación del servicio en AWS. Las pruebas se ejecutan en el IDE, llaman a la función de entrada del controlador Lambda con un evento generado y simulan flujos satisfactorios y casos extremos (los casos extremos se simulan con simulacros).
Pruebas de extremo a extremo que activan todo el servicio en AWS con un evento de entrada del cliente.
Mi metodología de pruebas
En esta sección, presentaré mi enfoque para las pruebas sin servidor y cómo diseño las pruebas necesarias para los microservicios sin servidor basados en la pirámide de pruebas sin servidor.
Baso mi enfoque en si las funciones Lambda están presentes en el flujo que me gustaría probar.
Se incluyen funciones Lambda
Aprendimos cómo probar funciones Lambda en lapublicación anterior .
Seguimos las pautas de la pirámide de pruebas y agregamos pruebas unitarias, de integración y de extremo a extremo a nuestra función Lambda.
Para las pruebas de integración, debemos generar el evento de entrada adecuado según el disparador Lambda asincrónico: puede ser una lista de eventos SQS (un lote), un evento EventBridge, un evento de transmisiones de DynamoDB, etc.
Para las pruebas de extremo a extremo, debemos activar la cadena de eventos que eventualmente activará la función Lambda en nuestra cuenta de AWS.
Las funciones Lambda no están incluidas
Analicemos casos de uso en los que no hay funciones Lambda en su microservicio.
Me vienen a la mente algunos ejemplos: una máquina de estados Step Function con funciones intrínsecas y tuberías EventBridge que realizan un proceso ETL y envían un evento a un bus EventBridge.
¿Cómo se prueban? No se pueden escribir pruebas unitarias o de integración como se hacía para las funciones Lambda; no hay código ni punto de entrada para activar localmente; ¡todo es configuración de infraestructura!
Debería preguntarse: ¿DEBERÍA probar estos servicios administrados por AWS o centrarme en el panorama general: el destino del evento y los efectos secundarios?
Mi respuesta es: Sí, todo lo que podemos y DEBEMOS hacer es una prueba de extremo a extremo.
Escribiremos pruebas de extremo a extremo, activaremos la cadena de eventos, validaremos sus efectos secundarios y garantizaremos que el evento llegue al final del camino correctamente como se espera.
Veamos algunos ejemplos y veamos cómo probar el servicio.
Prueba de flujos de mensajes asincrónicos
Un flujo puro asincrónico impulsado por eventos.
Está involucrada una función Lambda, por lo que escribiremos pruebas unitarias y de integración.
Las pruebas de integración generarán una lista de registros (consulte el ejemplo de evento de AWS SQS), llamarán al controlador lambda y validarán sus efectos secundarios.
Los efectos secundarios de la función Lambda pueden incluir escribir en una tabla de DynamoDB, llamar a una API, etc. En las pruebas de integración, puede simular las llamadas a estos efectos secundarios localmente y afirmar que se llaman y se llaman con los parámetros correctos.
También es crucial en este caso asegurarse de que la función Lambda, que recibe un evento de entrada SQS en forma de una lista de eventos (un lote), no genere una excepción no detectada que haga que todo el lote de eventos se devuelva a la cola.
Tenga en cuenta que, en este caso, no podemos simular ningún efecto secundario relacionado con SQS localmente, como:
Verificar el manejo adecuado de fallas parciales.
Validamos que hayamos configurado correctamente una cola de mensajes no entregados de SQS.
Por lo tanto, estos efectos secundarios se comprobarán únicamente mediante pruebas E2E.
Para lograr un flujo de E2E satisfactorio, publique un mensaje de SNS en el tema de SNS a través del SDK de AWS y valide los efectos secundarios de la función ('colocar elemento' en una tabla de DynamoDB, etc.). Otra opción es sondear el grupo de registros de la función, filtrar por la marca de tiempo de registro esperada y verificar que la función haya alcanzado un mensaje de registro específico que afirme que se produjo la acción.
En caso de fallas E2E, asegúrese de leer toda la documentación relacionada con el servicio administrado.
Amazon SQS tiene documentación muy informativa sobre el manejo de fallas parciales y la integración de la cola de mensajes no entregados.
Puede publicar eventos malformados en el tema SNS y asegurarse de que se envíen a la cola de mensajes inactivos preconfigurada esperando y recuperando (con un tiempo de espera) mensajes de la cola de mensajes inactivos de SQS hasta que se encuentre el evento esperado (la prueba pasa) o se produzca un tiempo de espera (la prueba falla).
Prueba de flujos sincrónicos y asincrónicos
Este caso de uso contiene flujos sincrónicos y asincrónicos: los dos primeros son sincrónicos y el último asincrónico.
Una API Gateway recibe una solicitud POST y escribe en una tabla de DynamoDB sin que intervenga una función Lambda (usa un proxy de servicio de AWS ). El cambio de tabla de DynamoDB activa un evento de transmisión de DynamoDB que activa una función Lambda.
No puede probar localmente en el IDE que API Gateway y verificar que escribe en DynamoDB.
Solo puede realizar pruebas de extremo a extremo que envíen la solicitud POST requerida y validen el efecto secundario que se produjo y la escritura del elemento. Puede hacerlo verificando directamente la tabla de DynamoDB o llamando a una API REST de elemento GET en API Gateway (suponiendo que exista dicha API).
Ahora, probemos el flujo asincrónico.
Se utiliza una función Lambda para que podamos escribir pruebas unitarias y de integración.
La prueba de integraciones generará un evento de entrada basado en el esquema de eventos de transmisión de DynamoDB.
Para simular errores, puede inyectar datos de un evento de entrada no válido, llamar al controlador de la función Lambda en el IDE y asegurarse de que lo gestione correctamente. Puede hacerlo simulando una función de gestión de errores específica y afirmando que se llamó y que se llamó con los parámetros correctos.
Para las pruebas de extremo a extremo, utilizaremos la prueba para la parte sincrónica. Ahora, aquí es donde se complica la cosa. Necesitamos entender cuál es el efecto secundario de Lambda. No podemos utilizar su código de retorno ya que se activa de forma asincrónica y no devuelve una respuesta que podamos obtener.
Necesitaremos verificar su efecto secundario. Si la función escribe en la tabla de DynamoDB, utilizaremos un mecanismo de sondeo (dentro de los límites de lo razonable y estableceremos un tiempo de espera breve y algunos reintentos) y comprobaremos la entrada de DynamoDB llamando a la API de obtención (si no hay API, utilizaremos el SDK de AWS para ver la tabla de DynamoDB directamente). Este método se aplica a cualquier otro efecto secundario que tenga.
Otra opción es sondear el grupo de registro de funciones, como se hizo en el ejemplo anterior y validar que haya procesado el evento correctamente.
Tenga en cuenta que, si el efecto secundario es difícil de validar en el flujo E2E, al menos debe validarse en las pruebas de integración. Una vez que el flujo de prueba de integración lo valide, la afirmación del grupo de registros puede ser suficiente.
Prueba de flujos asincrónicos no basados en Lambda
La definición de la tubería EventBridge:
En este caso, tenemos una tubería EventBridge no basada en Lambda:
Establece el evento de origen desde una cola SQS.
Filtra el evento según una configuración predefinida.
Enriquece el evento con una máquina de estados de función escalonada que contiene solo funciones intrínsecas (no hay funciones Lambda involucradas) y devuelve un evento enriquecido.
Envía el evento enriquecido a un tema de SNS.
En este caso, utilizamos un servicio Serverless administrado por AWS y no escribimos ningún código de función Lambda. Nuestro "código" es el código de configuración de la infraestructura que crea estos recursos en AWS:
La máquina de estados de función escalonada
La cola SQS
El tema de las redes sociales
La tubería EventBridge en sí
Todos los roles necesarios y la configuración que une los recursos
Como no interviene ninguna función Lambda, solo podemos escribir pruebas de extremo a extremo.
Necesitaremos escribir una prueba que coloque un mensaje en la cola de entrada SQS (que coincida con el filtro de tubería) y mirar el final de la cadena, el tema SNS.
En nuestra cuenta de entorno de prueba (no de producción), agregaremos una cola SQS solo de prueba para suscribirse al tema SNS de destino. No agregaremos este SQS en entornos de producción.
En nuestra prueba, buscaremos mensajes del destino de prueba SQS hasta que se reciba un mensaje o se alcance un tiempo de espera. La prueba fallará si encontramos un tiempo de espera en nuestro sondeo, lo que significa que el mensaje SNS no se envió, o si recibimos un mensaje SQS mal formado que no coincide con todo el esquema de mensajes enriquecidos que se suponía que debía producir la tubería EventBridge.
Otra opción para las pruebas E2E es probar individualmente la máquina de estados de Step Function; activarla con una entrada, esperar a que finalice su ejecución y validar su salida a través de la API del SDK de AWS, independientemente de si enriqueció el evento de entrada correctamente o no. También debe probar casos de uso en los que las entradas no válidas llegan a un estado de "error" en la máquina de estados.
Algunas observaciones:
Si bien no escribimos NINGUNA línea de código de función Lambda, sí escribimos partes de lógica en el código de configuración de infraestructura, ya sea que los pasos intrínsecos de la función de paso o la parte del filtro de tubería de EventBridge contengan lógica de esquema de dominio empresarial.
Requerimos menos pruebas (ni de integración ni de unidad), pero creo que las pruebas son menos intuitivas de escribir.
Solo podemos escribir pruebas E2E que activen recursos de AWS y se ejecuten en nuestra cuenta de AWS.