Prueba de funciones y aplicaciones sin servidor - AWS Lambda

Prueba de funciones y aplicaciones sin servidor

Para probar las funciones sin servidor, se utilizan tipos y técnicas de prueba tradicionales, pero también se debe considerar la posibilidad de probar las aplicaciones sin servidor en conjunto. Las pruebas basadas en la nube proporcionan la medida más precisa de la calidad tanto de las funciones como de las aplicaciones sin servidor.

Una arquitectura de aplicaciones sin servidor incluye servicios administrados que proporcionan las funcionalidades críticas de las aplicaciones mediante llamadas a la API. Por este motivo, el ciclo de desarrollo debe incluir pruebas automatizadas que verifiquen las funcionalidades cuando la función y los servicios interactúen.

Si no crea pruebas basadas en la nube, pueden surgir problemas debido a las diferencias entre su entorno local y el entorno implementado. El proceso de integración continua debe ejecutar pruebas con un conjunto de recursos aprovisionados en la nube antes de promover el código al siguiente entorno de implementación, como el control de calidad, el ensayo o la producción.

Siga leyendo esta breve guía para obtener información sobre las estrategias de prueba para aplicaciones sin servidor, o visite el repositorio de ejemplos de pruebas sin servidor a fin de profundizar en ejemplos prácticos y específicos para el lenguaje y el tiempo de ejecución de su elección.

illustration showing the relationship between types of tests

Para las pruebas sin servidor, seguirá escribiendo pruebas unitarias, de integración e integrales.

  • Pruebas unitarias: pruebas que se ejecutan en un bloque de código aislado. Por ejemplo, verificar la lógica empresarial para calcular los gastos de envío en función de un elemento y un destino determinados.

  • Pruebas de integración: pruebas en las que participan dos o más componentes o servicios que interactúan, normalmente en un entorno de nube. Por ejemplo, verificar si una función procesa los eventos de una cola.

  • Pruebas integrales: pruebas que verifican el comportamiento de toda una aplicación. Por ejemplo, garantizar que la infraestructura esté configurada correctamente y que los eventos fluyan entre los servicios tal como se espera para registrar el pedido de un cliente.

Resultados empresariales específicos

Probar soluciones sin servidor puede requerir un poco más de tiempo para configurar las pruebas que verifiquen las interacciones entre los servicios impulsados por eventos. Tenga en cuenta los siguientes motivos empresariales prácticos al leer esta guía:

  • Aumente la calidad de una aplicación

  • Reduzca el tiempo necesario para crear características y corregir errores

La calidad de una aplicación depende de probar una variedad de escenarios para verificar su funcionalidad. Considerar detenidamente los escenarios empresariales y automatizar esas pruebas para que se ejecuten en los servicios en la nube mejorará la calidad de su aplicación.

Los errores de software y los problemas de configuración afectan mucho menos el costo y la programación cuando se detectan durante un ciclo de desarrollo iterativo. Si los problemas no se detectan durante el desarrollo, más personas tienen que esforzarse el doble para encontrar y solucionar problemas durante el proceso de producción.

Una estrategia de pruebas sin servidor bien planificada aumentará la calidad del software y mejorará el tiempo de iteración al verificar que las funciones de Lambda y las aplicaciones funcionen según lo esperado en un entorno de nube.

Qué se debe probar

Recomendamos adoptar una estrategia de pruebas que pruebe los comportamientos de los servicios administrados, la configuración de la nube, las políticas de seguridad y la integración con el código para mejorar la calidad del software. Las pruebas de comportamiento, también conocidas como pruebas de caja negra, verifican que un sistema funcione como se espera sin conocer todos los aspectos internos.

  • Ejecute pruebas unitarias para comprobar la lógica empresarial dentro de las funciones de Lambda.

  • Verifique que los servicios integrados estén realmente invocados y que los parámetros de entrada sean correctos.

  • Compruebe que un evento pase por todos los servicios esperados de principio a fin en un flujo de trabajo.

En la arquitectura tradicional basada en servidores, los equipos suelen definir un ámbito de prueba para incluir únicamente el código que se ejecuta en el servidor de aplicaciones. Otros componentes, servicios o dependencias a menudo se consideran externos y quedan fuera del ámbito de las pruebas.

Las aplicaciones sin servidor suelen constar de pequeñas unidades de trabajo, como las funciones de Lambda que recuperan productos de una base de datos, procesan elementos de una cola o cambian el tamaño de una imagen almacenada. Cada componente se ejecuta en su propio entorno. Es probable que los equipos sean responsables de muchas de estas pequeñas unidades dentro de una sola aplicación.

Algunas funcionalidades de la aplicación pueden delegarse por completo a servicios administrados, como Amazon S3, o crearse sin utilizar ningún código desarrollado internamente. No es necesario probar estos servicios administrados, pero sí la integración con ellos.

Cómo efectuar las pruebas sin servidor

Es probable que esté familiarizado con la forma de probar aplicaciones implementadas de manera local: escribe pruebas que se ejecutan con código que se ejecuta por completo en el sistema operativo de escritorio o dentro de contenedores. Por ejemplo, puede invocar un componente de servicio web local con una solicitud y, a continuación, hacer afirmaciones sobre la respuesta.

Las soluciones sin servidor se crean a partir del código de funciones y de los servicios administrados basados en la nube, como colas, bases de datos, buses de eventos y sistemas de mensajería. Todos estos componentes están conectados a través de una arquitectura basada en eventos, en la que los mensajes, denominados eventos, fluyen de un recurso a otro. Estas interacciones pueden ser sincrónicas, por ejemplo, cuando un servicio web devuelve resultados de forma inmediata, o una acción asincrónica que se completa más adelante, como colocar elementos en una cola o iniciar un paso de un flujo de trabajo. Su estrategia de pruebas debe incluir ambos escenarios y probar las interacciones entre los servicios. En el caso de las interacciones asincrónicas, es posible que necesite detectar efectos secundarios en los componentes posteriores que tal vez no se puedan observar de inmediato.

No es práctico replicar un entorno de nube completo, incluidas las colas, las tablas de bases de datos, los buses de eventos, las políticas de seguridad y más. Inevitablemente, encontrará problemas debido a las diferencias entre su entorno local y los entornos implementados en la nube. Las variaciones entre los entornos aumentarán el tiempo de reproducción y corrección de errores.

En las aplicaciones sin servidor, los componentes de la arquitectura suelen existir completamente en la nube, por lo que es necesario realizar pruebas con el código y los servicios de la nube para desarrollar características y corregir errores.

Técnicas de pruebas

En la práctica, es probable que su estrategia de pruebas incluya una combinación de técnicas para aumentar la calidad de sus soluciones. Utilizará pruebas interactivas rápidas para depurar las funciones en la consola y pruebas unitarias automatizadas para comprobar la lógica empresarial aislada, verificará las llamadas a servicios externos con simulaciones y realizará pruebas ocasionales con emuladores que imitan un servicio.

  • Pruebas en la nube: implementa la infraestructura y el código para realizar pruebas con servicios reales, políticas de seguridad, configuraciones y parámetros específicos de la infraestructura. Las pruebas basadas en la nube proporcionan la medida más precisa de la calidad del código.

    Depurar una función en la consola es una forma rápida de realizar pruebas en la nube. Puede elegir entre una biblioteca de ejemplos de eventos de prueba o crear un evento personalizado para probar una función de forma aislada. También puede compartir los eventos de prueba a través de la consola con su equipo.

    Para automatizar las pruebas durante el ciclo de vida de desarrollo y compilación, tendrá que realizar las pruebas fuera de la consola. Consulte las secciones de pruebas específicas para cada lenguaje de esta guía para conocer las estrategias y los recursos de automatización.

  • Pruebas con simulaciones (también denominadas falsificaciones): las simulaciones son objetos del código que simulan y sustituyen a un servicio externo. Las simulaciones proporcionan un comportamiento predefinido para verificar las llamadas de servicio y los parámetros. Una falsificación es un despliegue simulado que utiliza atajos para simplificar o mejorar el rendimiento. Por ejemplo, un objeto de acceso a datos falso puede devolver datos de un almacén de datos en memoria. Las simulaciones pueden imitar y simplificar dependencias complejas, pero también pueden generar más simulaciones para reemplazar las dependencias anidadas.

  • Pruebas con emuladores: puede configurar aplicaciones (a veces de terceros) para que imiten un servicio en la nube en su entorno local. La velocidad es su punto fuerte, pero la configuración y la paridad con los servicios de producción son su punto débil. Use los emuladores con moderación.

Pruebas en la nube

Las pruebas en la nube son valiosas para todas las fases de las pruebas, incluidas las pruebas unitarias, las pruebas de integración y las pruebas integrales. Cuando realice pruebas con código basado en la nube que también interactúa con los servicios basados en la nube, obtiene la medida más precisa de la calidad del código.

Una forma práctica de ejecutar una función de Lambda en la nube es con un evento de prueba en la AWS Management Console. Un evento de prueba es una entrada JSON a su función. Si la función no requiere una entrada, el evento puede ser un documento JSON vacío ({}). La consola proporciona ejemplos de eventos para una variedad de integraciones de servicios. Después de crear un evento en la consola, también puede compartirlo con su equipo para que las pruebas sean más sencillas y coherentes.

Aprenda a depurar una función de ejemplo en la consola.

nota

Si bien ejecutar funciones en la consola es una forma rápida de depurar, automatizar los ciclos de prueba es fundamental para aumentar la calidad de la aplicación y la velocidad de desarrollo.

Los ejemplos de automatización de pruebas están disponibles en el repositorio de ejemplos de pruebas sin servidor. La siguiente línea de comandos ejecuta un ejemplo de prueba de integración automática de Python:

python -m pytest -s tests/integration -v

Aunque la prueba se ejecuta de forma local, interactúa con los recursos basados en la nube. Estos recursos se han implementado mediante AWS Serverless Application Model y la herramienta de la línea de comandos de AWS SAM. El código de prueba recupera primero las salidas de la pila implementada, que incluyen el punto de conexión de la API, el ARN de la función y el rol de seguridad. A continuación, la prueba envía una solicitud al punto de conexión de la API, que responde con una lista de buckets de Amazon S3. Esta prueba se ejecuta en su totalidad con recursos basados en la nube para verificar que esos recursos estén implementados, protegidos y funcionen según lo esperado.

========================= test session starts ========================= platform darwin -- Python 3.10.10, pytest-7.3.1, pluggy-1.0.0 -- /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda/venv/bin/python cachedir: .pytest_cache rootdir: /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda plugins: mock-3.10.0 collected 1 item tests/integration/test_api_gateway.py::TestApiGateway::test_api_gateway --> Stack outputs: HelloWorldApi = https://p7teqs3162.execute-api.us-west-2.amazonaws.com/Prod/hello/ > API Gateway endpoint URL for Prod stage for Hello World function PythonTestDemo = arn:aws:lambda:us-west-2:1234567890:function:testing-apigw-lambda-PythonTestDemo-iSij8evaTdxl > Hello World Lambda Function ARN PythonTestDemoIamRole = arn:aws:iam::1234567890:role/testing-apigw-lambda-PythonTestDemoRole-IZELQQ9MG4HQ > Implicit IAM Role created for Hello World function --> Found API endpoint for "testing-apigw-lambda" stack... --> https://p7teqs3162.execute-api.us-west-2.amazonaws.com/Prod/hello/ API Gateway response: amplify-dev-123456789-deployment|myapp-prod-p-loggingbucket-123456|s3-java-bucket-123456789 PASSED ========================= 1 passed in 1.53s =========================

Para el desarrollo de aplicaciones nativas en la nube, las pruebas en la nube ofrecen las siguientes ventajas:

  • Puede probar todos los servicios disponibles.

  • Siempre se utilizan las API de servicio y los valores devueltos más recientes.

  • Un entorno de pruebas en la nube se parece mucho a su entorno de producción.

  • Las pruebas pueden abarcar políticas de seguridad, cuotas de servicio, configuraciones y parámetros específicos de la infraestructura.

  • Cada desarrollador puede crear rápidamente uno o más entornos de prueba en la nube.

  • Las pruebas en la nube aumentan la confianza en que el código se ejecutará correctamente en producción.

Las pruebas en la nube tienen algunas desventajas. El aspecto negativo más obvio de las pruebas en la nube es que las implementaciones en entornos de nube suelen tardar más que las implementaciones en entornos de escritorio locales.

Por suerte, herramientas como el AWS Serverless Application Model (AWS SAM) Accelerate, el modo de vigilancia de AWS Cloud Development Kit (AWSCDK) y SST (de terceros) reducen la latencia relacionada con las iteraciones de implementación en la nube. Estas herramientas pueden monitorear su infraestructura y código e implementar automáticamente actualizaciones progresivas en su entorno de nube.

nota

Consulte cómo crear infraestructura como código en la Guía para desarrolladores sin servidor a fin de obtener más información sobre AWS Serverless Application Model, AWS CloudFormation y AWS Cloud Development Kit (AWS CDK).

A diferencia de las pruebas locales, las pruebas en la nube requieren recursos adicionales, lo que puede generar costos de servicio. La creación de entornos de prueba aislados puede aumentar la carga de trabajo de sus equipos de DevOps, especialmente en organizaciones con controles estrictos sobre las cuentas y la infraestructura. Aun así, cuando se trabaja con escenarios de infraestructura complejos, el costo en cuanto al tiempo de los desarrolladores para configurar y mantener un entorno local complejo puede ser similar (o más costoso) al de utilizar entornos de prueba desechables creados con herramientas de automatización de infraestructura como código.

Las pruebas en la nube, incluso teniendo en cuenta estas consideraciones, siguen siendo la mejor manera de garantizar la calidad de sus soluciones sin servidor.

Pruebas con simulaciones

Las pruebas con simulaciones son una técnica en la que se crean objetos de reemplazo en el código para simular el comportamiento de un servicio en la nube.

Por ejemplo, puede escribir una prueba que utilice una simulación del servicio Amazon S3 que devuelva una respuesta específica cada vez que se llame al método CreateObject. Cuando se ejecuta una prueba, el simulacro devuelve la respuesta programada sin llamar a Amazon S3 ni a ningún otro punto de conexión del servicio.

Los objetos simulados suelen generarse mediante un marco simulado para reducir el esfuerzo de desarrollo. Algunos marcos simulados son genéricos y otros están diseñados específicamente para los AWS SDK, como Moto, una biblioteca de Python para simular servicios y recursos de AWS.

Tenga en cuenta que los objetos simulados se diferencian de los emuladores en que las simulaciones suelen ser creadas o configuradas por un desarrollador como parte del código de prueba, mientras que los emuladores son aplicaciones independientes que exponen la funcionalidad de la misma manera que los sistemas que emulan.

Entre las ventajas de utilizar simulaciones se incluyen las siguientes:

  • Las simulaciones pueden simular servicios de terceros que escapan al control de su aplicación, como las API y los proveedores de software como servicio (SaaS), sin necesidad de tener acceso directo a esos servicios.

  • Las simulaciones son útiles para probar las condiciones de error, especialmente cuando dichas condiciones son difíciles de simular, como una interrupción del servicio.

  • Las simulaciones pueden proporcionar pruebas locales rápidas una vez configuradas.

  • Las simulaciones pueden proporcionar un comportamiento sustituto para prácticamente cualquier tipo de objeto, por lo que las estrategias de simulación pueden ofrecer cobertura a una variedad de servicios más amplia que los emuladores.

  • Cuando hay nuevas características o comportamientos disponibles, las pruebas simuladas pueden reaccionar más rápidamente. Al utilizar un marco simulado genérico, puede simular nuevas características tan pronto como el AWS SDK actualizado esté disponible.

Las pruebas simuladas tienen las siguientes desventajas:

  • Por lo general, las simulaciones requieren un esfuerzo no trivial de preparación y configuración, especialmente cuando se trata de determinar los valores devueltos de diferentes servicios para simular correctamente las respuestas.

  • Los desarrolladores deben escribir, configurar y mantener las simulaciones, lo que aumenta sus responsabilidades.

  • Es posible que necesite tener acceso a la nube para comprender las API y devolver los valores de los servicios.

  • Las simulaciones pueden ser difíciles de mantener. Cuando cambien las firmas de la API en la nube simuladas o evolucionen los esquemas de valores de retorno, debe actualizar las simulaciones. Las simulaciones también requieren actualizaciones si amplía la lógica de la aplicación para realizar llamadas a nuevas API.

  • Las pruebas que utilizan simulaciones pueden funcionar en entornos de escritorio pero fallar en la nube. Es posible que los resultados no coincidan con la API actual. La configuración del servicio y las cuotas no se pueden probar.

  • Los marcos simulados son limitados a la hora de probar o detectar políticas o limitaciones de cuotas de AWS Identity and Access Management (IAM). Si bien las simulaciones son mejores para simular cuando se produce un error en la autorización o se supera una cuota, las pruebas no pueden determinar qué resultado se producirá realmente en un entorno de producción.

Pruebas con emulación

Los emuladores suelen ser una aplicación que se ejecuta de forma local y que imita un servicio de producción de AWS.

Los emuladores tienen API que se asemejan a las de la nube y ofrecen valores de retorno similares. También pueden simular los cambios de estado que se inician mediante llamadas a la API. Por ejemplo, puede usar AWS SAM para ejecutar una función con AWS SAM local para emular el servicio Lambda y poder invocar rápidamente una función. Para obtener detalles, consulte AWS SAM local  en la Guía para desarrolladores de AWS Serverless Application Model.

Entre las ventajas de realizar pruebas con emuladores se incluyen las siguientes:

  • Los emuladores pueden facilitar las iteraciones y pruebas rápidas del desarrollo local.

  • Los emuladores proporcionan un entorno familiar para los desarrolladores acostumbrados a desarrollar código en un entorno local. Por ejemplo, si está familiarizado con el desarrollo de una aplicación de n niveles, es posible que tenga un motor de base de datos y un servidor web, similares a los que se ejecutan en producción, en su equipo local para proporcionar una capacidad de prueba rápida, local y aislada.

  • Los emuladores no requieren ningún cambio en la infraestructura de la nube (como las cuentas en la nube de los desarrolladores), por lo que son fáciles de implementar con los patrones de prueba existentes.

Las pruebas con emuladores tienen las siguientes desventajas:

  • Los emuladores pueden ser difíciles de configurar y replicar, especialmente cuando se utilizan en canalizaciones de CI/CD. Esto puede aumentar la carga de trabajo del personal de TI o de los desarrolladores que administran su propio software.

  • Las características y las API emuladas suelen quedar un paso por detrás de las actualizaciones del servicio. Esto puede generar errores porque el código probado no coincide con la API real e impide la adopción de nuevas características.

  • Los emuladores requieren soporte, actualizaciones, correcciones de errores y mejoras en la paridad de características. Son responsabilidad del autor del emulador, que puede ser una empresa externa.

  • Las pruebas que se basan en emuladores pueden ofrecer resultados satisfactorios a nivel local, pero fallan en la nube debido a las políticas de seguridad de producción, a las configuraciones entre servicios o a que se superan las cuotas de Lambda.

  • Muchos servicios de AWS no tienen emuladores disponibles. Si confía en la emulación, es posible que no disponga de una opción de prueba satisfactoria para algunas partes de su aplicación.

Prácticas recomendadas

En las siguientes secciones, se proporcionan recomendaciones para realizar pruebas satisfactorias de aplicaciones sin servidor.

Puede encontrar ejemplos prácticos de pruebas y automatización de pruebas en el repositorio de ejemplos de pruebas sin servidor.

Priorice las pruebas en la nube

Las pruebas en la nube ofrecen la cobertura de pruebas más confiable, precisa y completa. Al realizar pruebas en el contexto de la nube, se comprobarán de manera exhaustiva no solo la lógica empresarial, sino también las políticas de seguridad, las configuraciones de servicios, las cuotas y las firmas de API y los valores devueltos más actualizados.

Estructure su código para que sea fácil de probar

Simplifique sus pruebas y funciones de Lambda al separar el código específico de Lambda de su lógica empresarial principal.

El controlador de la función de Lambda debe ser un adaptador compacto que tome los datos de los eventos y que transmita solo los detalles importantes a sus métodos de lógica empresarial. Con esta estrategia, puede empaquetar pruebas exhaustivas en torno a su lógica empresarial sin preocuparse por los detalles específicos de Lambda. Las funciones de AWS Lambda de no deberían requerir la configuración de un entorno complejo o una gran cantidad de dependencias para crear e inicializar el componente que se está probando.

En términos generales, debe escribir un controlador que extraiga y valide los datos de los objetos de evento y contexto entrantes y, a continuación, envíe esa entrada a los métodos que ejecuten su lógica empresarial.

Acelere los ciclos de retroalimentación del desarrollo

Existen herramientas y técnicas para acelerar los ciclos de retroalimentación del desarrollo. Por ejemplo, tanto AWS SAM Accelerate como el modo de vigilancia de AWS CDK reducen el tiempo necesario para actualizar los entornos de nube.

Los ejemplos del repositorio de ejemplos de pruebas sin servidor de GitHub exploran algunas de estas técnicas.

También recomendamos que cree y pruebe los recursos en la nube lo antes posible durante el desarrollo, no solo después de comprobar el control del código fuente. Esta práctica permite una exploración y experimentación más rápidas a la hora de desarrollar soluciones. Además, la automatización de la implementación desde un equipo de desarrollo lo ayuda a descubrir los problemas de configuración de la nube con mayor rapidez y reduce el esfuerzo desperdiciado en las actualizaciones y los procesos de revisión del código.

Céntrese en las pruebas de integración

Cuando se crean aplicaciones con Lambda, se recomienda probar los componentes juntos.

Las pruebas que se ejecutan en dos o más componentes arquitectónicos se denominan pruebas de integración. El objetivo de las pruebas de integración es comprender no solo cómo se ejecutará el código en todos los componentes, sino también cómo se comportará el entorno que aloja el código. Las pruebas integrales son tipos especiales de pruebas de integración que verifican los comportamientos de toda una aplicación.

Para crear pruebas de integración, implemente la aplicación en un entorno de nube. Esto se puede hacer desde un entorno local o mediante una canalización de CI/CD. A continuación, escriba pruebas para ejercitar el sistema bajo prueba (SUT) y validar el comportamiento esperado.

Por ejemplo, el sistema bajo prueba puede ser una aplicación que utilice API Gateway, Lambda y DynamoDB. Una prueba puede realizar una llamada HTTP sintética a un punto de conexión de API Gateway y validar que la respuesta haya incluido la carga esperada. Esta prueba valida que el código de AWS Lambda es correcto y que cada servicio está configurado de forma adecuada para gestionar la solicitud, incluidos los permisos de IAM entre ellos. Además, puede diseñar la prueba para escribir registros de varios tamaños a fin de verificar que sus cuotas de servicio, como el tamaño máximo de registro en DynamoDB, están configuradas correctamente.

Diagrama que muestra un sistema bajo prueba compuesto por tres servicios.

Cree entornos de pruebas aislados

Las pruebas en la nube suelen requerir entornos de desarrollo aislados, de modo que las pruebas, los datos y los eventos no se superpongan.

Un enfoque consiste en proporcionar a cada desarrollador una cuenta de AWS dedicada. Esto evitará conflictos con la nomenclatura de los recursos que pueden ocurrir cuando varios desarrolladores que trabajan en una base de código compartida intentan implementar recursos o invocar una API.

Los procesos de prueba automatizados deben crear recursos con nombres únicos para cada pila. Por ejemplo, puede configurar scripts o archivos de configuración TOML para que los comandos de la CLI de AWS SAM sam deploy o sam sync especifiquen automáticamente una pila con un prefijo único.

En algunos casos, los desarrolladores comparten una cuenta de AWS. Esto puede deberse a que hay recursos en su pila que son costosos de operar o de aprovisionar y configurar. Por ejemplo, se puede compartir una base de datos para facilitar la configuración y la siembra de datos de forma adecuada.

Si los desarrolladores comparten una cuenta, debe establecer límites para identificar la propiedad y eliminar la superposición. Una forma de hacerlo consiste en poner un prefijo a los nombres de las pilas con los ID de usuario de los desarrolladores. Otro enfoque popular es configurar pilas basadas en ramas de código. Con los límites de las ramas, los entornos están aislados, pero los desarrolladores pueden seguir compartiendo recursos, como una base de datos relacional. Este enfoque es una práctica recomendada cuando los desarrolladores trabajan en más de una rama a la vez.

Las pruebas en la nube son valiosas para todas las fases de las pruebas, incluidas las pruebas unitarias, las pruebas de integración y las pruebas integrales. Mantener un aislamiento adecuado es esencial, pero aun así querrá que su entorno de control de calidad se parezca lo más posible a su entorno de producción. Por este motivo, los equipos agregan procesos de control de cambios para los entornos de control de calidad.

En los entornos de preproducción y producción, los límites se suelen establecer a nivel de cuenta para aislar las cargas de trabajo de los problemas de vecinos ruidosos e implementar controles de seguridad con privilegios mínimos a fin de proteger los datos confidenciales. Las cargas de trabajo tienen cuotas. No querrá que sus pruebas consuman las cuotas asignadas a la producción (vecinos ruidosos) ni tengan acceso a los datos de los clientes. Las pruebas de carga son otra actividad que debe aislar de la pila de producción.

En todos los casos, los entornos deben configurarse con alertas y controles para evitar gastos innecesarios. Por ejemplo, puede limitar el tipo, el nivel o el tamaño de los recursos que se pueden crear y configurar alertas por correo electrónico cuando los costos estimados superen un umbral determinado.

Utilice simulaciones para una lógica empresarial aislada

Los marcos simulados son una herramienta valiosa para escribir pruebas unitarias rápidas. Son especialmente útiles cuando las pruebas cubren una lógica empresarial interna compleja, como cálculos o simulaciones matemáticas o financieras. Busque pruebas unitarias que tengan una gran cantidad de casos de prueba o variaciones de entrada, en las que esas entradas no cambien el patrón ni el contenido de las llamadas a otros servicios en la nube.

El código que se incluye en las pruebas unitarias con simulaciones también debe incluirse en las pruebas en la nube. Esto se recomienda porque un entorno de equipo portátil o de compilación para desarrolladores puede configurarse de forma diferente a un entorno de producción en la nube. Por ejemplo, las funciones de Lambda pueden utilizar más memoria o tiempo del asignado cuando se ejecutan con ciertos parámetros de entrada. O bien, el código puede incluir variables de entorno que no están configuradas de la misma manera (o no están configuradas en absoluto), y las diferencias pueden provocar que el código se comporte de manera diferente o que falle.

El beneficio de las simulaciones es menor en las pruebas de integración, ya que el nivel de esfuerzo para implementar las simulaciones necesarias aumenta con la cantidad de puntos de conexión. Las pruebas integrales no deben utilizar simulaciones, ya que estas pruebas suelen tratar con estados y lógicas complejas que no se pueden simular fácilmente con marcos simulados.

Por último, evite utilizar servicios en la nube simulados para validar el despliegue correcto de las llamadas de servicio. En su lugar, realice llamadas al servicio de nube en la nube para validar el comportamiento, la configuración y el despliegue funcional.

Use emuladores con moderación

Los emuladores pueden resultar útiles para algunos casos de uso, por ejemplo, para un equipo de desarrollo con acceso a Internet limitado, poco fiable o lento. Sin embargo, en la mayoría de los casos, opte por utilizar los emuladores con moderación.

Al evitar los emuladores, podrá crear e innovar con las características de servicio más recientes y las API actualizadas. No tendrá que esperar a que los proveedores publiquen sus productos para lograr la paridad de características. Reducirá los gastos iniciales y continuos de compra y configuración en múltiples sistemas de desarrollo y equipos de compilación. Además, evitará el problema de que muchos servicios en la nube simplemente no tienen emuladores disponibles. Una estrategia de pruebas que dependa de la emulación imposibilitará el uso de esos servicios (lo que podría generar soluciones alternativas más costosas) o producirá código y configuraciones que no estén bien probados.

Cuando utilice la emulación para realizar pruebas, deberá seguir realizando pruebas en la nube para verificar la configuración y probar las interacciones con los servicios en la nube que solo se pueden simular o imitar en un entorno emulado.

Desafíos al probar de forma local

Cuando utilice emuladores y llamadas simuladas para realizar pruebas en el escritorio local, es posible que experimente incoherencias en las pruebas a medida que el código avance de un entorno a otro en la canalización de CI/CD. Es posible que las pruebas unitarias para validar la lógica empresarial de la aplicación en el escritorio no prueben con precisión los aspectos críticos de los servicios en la nube.

En los siguientes ejemplos, se muestran casos para tener en cuenta al realizar pruebas locales con simulaciones y emuladores:

Ejemplo: la función de Lambda crea un bucket de S3

Si la lógica de una función de Lambda depende de la creación de un bucket de S3, una prueba completa debería confirmar que se llamó a Amazon S3 y que el bucket se creó correctamente.

  • En una configuración de prueba simulada, puede simular una respuesta correcta y, potencialmente, agregar un caso de prueba para gestionar una respuesta de error.

  • En un escenario de prueba de emulación, es posible que se llame a la API CreateBucket, pero debe tener en cuenta que la identidad que realiza la llamada local no procederá del servicio Lambda. La identidad de llamada no asumirá un rol de seguridad como lo haría en la nube, por lo que se utilizará en su lugar una autenticación de marcadores de posición, posiblemente con un rol o identidad de usuario más permisiva que será diferente cuando se ejecute en la nube.

Las configuraciones de simulación y emulación comprobarán qué hará la función de Lambda si llama a Amazon S3; sin embargo, esas pruebas no verificarán que la función de Lambda, tal como está configurada, sea capaz de crear correctamente el bucket de Amazon S3. Debe asegurarse de que el rol asignado a la función tenga una política de seguridad adjunta que permita a la función realizar la acción s3:CreateBucket. De lo contrario, es probable que la función falle cuando se implemente en un entorno de nube.

Ejemplo: la función de Lambda procesa mensajes de una cola de Amazon SQS

Si una cola de Amazon SQS es el origen de una función de Lambda, una prueba completa debería comprobar que la función de Lambda se invoca correctamente cuando se coloca un mensaje en una cola.

Las pruebas de emulación y simulación generalmente se configuran para ejecutar el código de la función de Lambda directamente y para simular la integración de Amazon SQS pasando una carga de eventos JSON (o un objeto deserializado) como entrada del controlador de funciones.

Las pruebas locales que simulan la integración de Amazon SQS comprobarán qué hará la función de Lambda cuando Amazon SQS la llame con una carga determinada, pero no verificarán que Amazon SQS invoque correctamente la función de Lambda cuando se implemente en un entorno de nube.

Algunos ejemplos de problemas de configuración que pueden surgir con Amazon SQS y Lambda son los siguientes:

  • El tiempo de espera de visibilidad de Amazon SQS es demasiado bajo, lo que provoca varias invocaciones cuando solo se tiene prevista una.

  • El rol de ejecución de la función de Lambda no permite leer los mensajes de la cola (a través de sqs:ReceiveMessagesqs:DeleteMessage o sqs:GetQueueAttributes).

  • El evento de ejemplo que se pasa a la función de Lambda supera la cuota de tamaño de los mensajes de Amazon SQS. Por lo tanto, la prueba no es válida porque Amazon SQS nunca podrá enviar un mensaje de ese tamaño.

Como se muestra en estos ejemplos, es probable que las pruebas que cubren la lógica empresarial, pero no las configuraciones entre los servicios en la nube, arrojen resultados poco fiables.

Preguntas frecuentes

Tengo una función de Lambda que realiza cálculos y devuelve un resultado sin llamar a ningún otro servicio. ¿Realmente necesito probarlo en la nube?

Sí. Las funciones de Lambda tienen parámetros de configuración que pueden cambiar el resultado de la prueba. Todo el código de la función de Lambda depende de la configuración del tiempo de espera y la memoria, lo que puede provocar un error en la función si esos ajustes no se configuran correctamente. Las políticas de Lambda también permiten el registro de salida estándar en Amazon CloudWatch. Incluso si su código no llama directamente a CloudWatch, se necesitan permisos para habilitar el registro. Este permiso obligatorio no se puede burlar ni emular con precisión.

¿Cómo pueden ayudar las pruebas en la nube a las pruebas unitarias? Si está en la nube y se conecta a otros recursos, ¿no es una prueba de integración?

Definimos las pruebas unitarias como las pruebas que funcionan en componentes arquitectónicos de forma aislada, pero esto no impide que las pruebas incluyan componentes que pueden llamar a otros servicios o utilizar alguna comunicación de red.

Muchas aplicaciones sin servidor tienen componentes arquitectónicos que se pueden probar de forma aislada, incluso en la nube. Un ejemplo es una función de Lambda que toma una entrada, procesa los datos y envía un mensaje a una cola de Amazon SQS. Una prueba unitaria de esta función probablemente comprobaría si los valores de entrada dan como resultado que ciertos valores estén presentes en el mensaje en cola.

Considere una prueba que se escribe con el patrón Organizar, Actuar, Afirmar:

  • Organizar: asigne recursos (una cola para recibir mensajes y la función que se está probando).

  • Actuar: llame a la función que se está probando.

  • Afirmar: recupere el mensaje enviado por la función y valide la salida.

Un enfoque de prueba simulada implicaría simular la cola con un objeto simulado en proceso y crear una instancia en proceso de la clase o módulo que contenga el código de la función de Lambda. Durante la fase de afirmación, el mensaje en cola se recuperaría del objeto de la simulación.

En un enfoque basado en la nube, la prueba crearía una cola de Amazon SQS para los fines de la prueba e implementaría la función de Lambda con variables de entorno configuradas para utilizar la cola aislada de Amazon SQS como destino de salida. Tras ejecutar la función de Lambda, la prueba recuperaría el mensaje de la cola de Amazon SQS.

La prueba basada en la nube ejecutaría el mismo código, afirmaría el mismo comportamiento y validaría la corrección funcional de la aplicación. Sin embargo, tendría la ventaja adicional de poder validar la configuración de la función de Lambda: el rol de IAM, las políticas de IAM y la configuración de memoria y tiempo de espera de la función.

Próximos pasos y recursos

Utilice los siguientes recursos para obtener más información y explorar ejemplos prácticos de pruebas.

Despliegue de ejemplo

El repositorio de ejemplos de pruebas sin servidor de GitHub contiene ejemplos concretos de pruebas que siguen los patrones y las prácticas recomendadas que se describen en esta guía. El repositorio contiene código de muestra y tutoriales guiados sobre los procesos de simulación, emulación y prueba en la nube descritos en las secciones anteriores. Utilice este repositorio para ponerse al día con la guía de pruebas sin servidor más reciente de AWS.

Documentación adicional

Visite Serverless Land para acceder a los blogs, videos y formaciones más recientes sobre tecnologías de AWS sin servidor.

También se recomienda leer las siguientes publicaciones del blog de AWS:

Herramientas