Esta es una traducción que desde EGA Futura ofrecemos como cortesía a toda la Ohana y comunidad de programadores , consultores , administradores y arquitectos de Salesforce para toda Iberoamérica .
El enlace a la publicación original, lo encontrarás al final de este artículo.
…
Escribir pruebas sólidas es crucial para crear aplicaciones comerciales confiables y eficientes. En esta publicación, haremos un repaso de las pruebas unitarias y presentaremos apex-mockery , una biblioteca liviana de pruebas unitarias de Apex que lo ayuda a escribir pruebas unitarias de Apex verdaderamente desacopladas usando simulacros y aserciones. Compartiremos ejemplos de código para ayudarlo a comprender cómo puede usar la biblioteca para crear pruebas unitarias fáciles de entender y de ejecución rápida.
Un repaso a las pruebas unitarias
Antes de echar un vistazo a la biblioteca de Apex-Mockery, demos un paso atrás y analicemos algunos de los conceptos básicos de las pruebas unitarias desde un punto de vista independiente de la tecnología. Luego, veremos Apex y discutiremos por qué la mayoría de nosotros debería escribir pruebas unitarias en lugar de pruebas de integración.
Las pruebas unitarias están en la base de la pirámide de prueba.
La ingeniería de software abarca múltiples tipos de pruebas: unidad, integración, servicio, interfaz de usuario funcional, de extremo a extremo, aceptación del usuario y más. Como dice Martin Fowler , podemos representar un buen equilibrio entre estos tipos de pruebas dentro del alcance de un proyecto representándolos como una pirámide.
Las etiquetas (tipos de prueba) pueden cambiar, pero el principio clave aquí es que las pruebas que se ejecutan rápido y con frecuencia deben estar en la parte inferior de la pirámide. Estos son los más fáciles de implementar y mantener (por lo que cuestan menos). Luego, a medida que subimos a la cima, aumentamos la complejidad y el costo: las pruebas se ejecutan más lentamente y se vuelven más difíciles de implementar y mantener.
En el contexto de esta publicación y en aras de la brevedad, nos centraremos únicamente en las pruebas unitarias. Estos son los primeros que debe implementar en cualquier proyecto, y deben ser una prioridad en su estrategia de prueba.
Por definición, las pruebas unitarias están destinadas a probar la menor cantidad de código (una unidad) de un proyecto. Las pruebas unitarias solo deben basarse en la lógica pura y estar completamente desvinculadas de sus dependencias (otras clases) y límites (otros servicios, como almacenamiento de datos o servicios web). Las pruebas unitarias deben ejecutarse rápido; no requieren una configuración de prueba particular, como la inserción de datos en la base de datos, y requieren que simule las dependencias de la clase bajo prueba.
Escribir pruebas unitarias de Apex en lugar de pruebas de integración
Apex se beneficia de una estrecha integración con la Plataforma de Salesforce y, si bien esta característica es excelente para cosas como acceder rápida y fácilmente a la base de datos, difumina las líneas de separación de preocupaciones entre la lógica y los servicios. Como consecuencia, es muy fácil escribir pruebas de integración de Apex en lugar de pruebas unitarias. Por ejemplo, el código de Apex a menudo se prueba junto con la base de datos utilizando declaraciones @TestSetup
y DML. Si bien estas pruebas de integración ayudan a lograr la cobertura, se basan en la base de datos y, por lo tanto, requieren más tiempo para ejecutarse que las pruebas unitarias "puras".
Como compartió Mitch Spano en su presentación de pruebas unitarias puras de Apex , la mayoría de las veces, no es necesario confiar en las pruebas de integración para probar capas de software de alto nivel, como controladores LWC, servicios y capas de aplicación. Gracias a la API de Stub de Apex lanzada en Spring '17, los desarrolladores pueden romper con esas dependencias en el contexto de las pruebas mediante la creación de su propia biblioteca/marco de pruebas unitarias o el uso de uno existente como apex-mockery.
Presentamos la burla del ápice
Como parte del trabajo de ingeniería de Salesforce, estábamos desarrollando un paquete administrado internamente y necesitábamos una biblioteca para escribir pruebas unitarias. Queríamos escribir pasos simples de "arreglar" (como en el patrón Arrange-Act-Assert ), escribir afirmaciones comprensibles y burlarnos de nuestras dependencias. Buscamos en todo el ecosistema una biblioteca fácil de leer y bien probada que pudiéramos usar para crear nuestro producto, pero no encontramos una combinación perfecta, por lo que decidimos escribir la nuestra. Estábamos tan contentos con la implementación final de la biblioteca que decidimos lanzarla como código abierto con el nombre apex-mockery .
La biblioteca apex-mockery proporciona una biblioteca de simulación simple, liviana y fácil de leer para Apex creada con la API Stub. La biblioteca está diseñada para que sea fácil de usar y brinde la mejor experiencia de desarrollador posible al generar simulacros y apéndices, configurar espías y escribir aserciones.
Lo guiaremos a través de un escenario de muestra para que pueda comprender el poder de la biblioteca con algunos ejemplos prácticos. Luego, le mostraremos cómo puede escribir pruebas para este proyecto de muestra en tres pasos:
- Crear simulacros y espías de métodos.
- Métodos de espionaje de trozo
- escribir afirmaciones
Ejemplo de escenario: pedidos de panadería y entrega
Considere el siguiente escenario de ejemplo: una panadería toma pedidos de pastelería y planifica las entregas utilizando un servicio dedicado. Los únicos datos que estamos considerando en el contexto de este escenario son los nombres de los pasteles y su fecha de entrega.
A continuación se muestra la implementación básica de nuestro escenario de panadería (el código completo está disponible en el repositorio del proyecto ).
Pastelería.cls
DeliveryService.cls
DeliveryServiceImpl.cls
Confirmación de pedido.cls
Panadería.cls
Ahora que hemos echado un vistazo a nuestro proyecto de muestra, echemos un vistazo a cómo podríamos escribir pruebas para el método Bakery.order
.
Paso 1: crea simulacros y espías de métodos
Para funcionar, la clase Bakery
necesita que se pase una instancia DeliveryService
en su constructor. En un contexto de producción, el servicio se proporciona con una instancia concreta DeliveryServiceImpl
de la siguiente manera:
Sin embargo, en el contexto de las pruebas unitarias, no debe usar una instancia de servicio real para garantizar el desacoplamiento. En otras palabras, DelivertServiceImpl
se probará unitariamente por sí solo, por lo que no es necesario que pruebe las dos clases integradas juntas. Puede reemplazar la dependencia del servicio con un simulacro que implemente la interfaz DeliverService
.
Así es como puede crear e inyectar fácilmente un simulacro de este tipo, gracias a apex-mockery:
Luego, su prueba necesita un espía, para que pueda controlar el comportamiento del método planDelivery
y ejecutar aserciones en sus llamadas.
Ahora que tiene un servicio simulado y un espía en su método planDelivery
, veamos cómo puede configurar su espía y ejecutar aserciones en él.
Paso 2: métodos de espionaje de trozo
Una vez que tenga una instancia simulada, puede controlar cómo se comportan sus métodos controlando sus valores de retorno y lanzando excepciones.
Utilice los métodos returns
y throwsException
para especificar un comportamiento predeterminado que se aplica a todas las llamadas a los métodos auxiliares. Luego, si es necesario, usa una combinación de whenCalledWith(<args>).thenReturn
y whenCalledWith(<args>).thenThrow
para aplicar comportamientos específicos a las llamadas a métodos que coincidan con los argumentos especificados.
Durante la ejecución de la prueba, apex-mockery comienza buscando una coincidencia en la configuración proporcionada por whenCalledWith
. Si no se encuentra ninguno, vuelve a la configuración predeterminada ( returns
o throwException
).
Veamos algunas situaciones comunes de configuración de stubs (ver más recetas ).
- Devolver algo cada vez que se llame
planDelivery
- Lanza una excepción cada vez que se llama
planDelivery
- Devuelve algo cuando se llama con un argumento específico
- Lanza una excepción cuando se llama con un argumento específico
Ahora que sabe cómo impulsar el comportamiento de su simulacro, puede agregar aserciones para probar su código.
Paso 3: Escribe afirmaciones
apex-mockery proporciona una API de afirmaciones fluidas. Tan pronto como comience su expectativa con Expect.that(mySpy)
, tendrá acceso a varios métodos de afirmación. La biblioteca viene con una serie de afirmaciones de comportamiento fáciles de usar, como:
Si los comparadores de argumentos básicos no son suficientes para sus necesidades, también puede crear sus propios comparadores de argumentos personalizados .
Uniendo el ejemplo completo
Ahora que vimos los pasos individuales, terminemos y echemos un vistazo a nuestra prueba para el método Bakery.order
. Observe cómo puede usar aserciones de burla de Apex, junto con las aserciones estándar de Apex de la clase system.Assert
, en sus pruebas.
palabras de cierre
Esto concluye nuestro recorrido por las pruebas unitarias y la biblioteca de Apex-Mockery. Aprendió cómo las pruebas unitarias desacopladas son más fáciles de escribir y ejecutar mucho más rápido. Tener pruebas rápidas acorta el ciclo de retroalimentación del ciclo de vida del desarrollo, reduce la duración de la ejecución del flujo de trabajo de CI y acelera las implementaciones. Estos factores permiten a los desarrolladores implementar y ejecutar pruebas con frecuencia, mejorando así la calidad.
apex-mockery lo ayuda a dirigir su proyecto en esta dirección. Consulte el repositorio del proyecto para comenzar. Encontrará la documentación de la biblioteca con las opciones de instrucciones de instalación (instalación de fuente o paquete desbloqueado), algunas recetas de muestra y una guía de migración. ¡Feliz prueba unitaria!
Sobre los autores
Ludovic Meurillon es ingeniero de software en el equipo de Service Cloud en Grenoble, Francia. Empujó el código a la producción durante años, disfruta eliminando más líneas de código de las que agrega y prefiere la programación en pares sobre las revisiones de código y los productos de trabajo sobre el diseño perfecto. Sígalo en Twitter @LudoMeurillon o consulte sus proyectos de GitHub @ludomeurillon .
Sébastien Colladon es CTA e ingeniero de software en el equipo de Service Cloud en París, Francia. Le encanta contribuir a hacer del ecosistema de Salesforce un lugar mejor y disfruta aprender y trabajar con otros. Consulte sus proyectos de GitHub @ scolladon .
Philippe Ozil es un defensor principal de desarrolladores en Salesforce, donde se enfoca en la plataforma de Salesforce. Escribe contenido técnico y habla con frecuencia en conferencias. Es un desarrollador full-stack y disfruta trabajar en proyectos DevOps, robótica y VR. Sígalo en Twitter @PhilippeOzil o consulte sus proyectos de GitHub @pozil .
Obtenga las últimas publicaciones de blog de desarrolladores de Salesforce y episodios de podcast a través de Slack o RSS.
Agregar a Slack Suscríbete a RSS