Se ha escrito mucho sobre las pruebas unitarias de componentes de React, reductores de Redux y demás, pero nos ha costado mucho encontrar artículos en profundidad sobre cómo configurar pruebas de integración completas y adecuadas para la pila moderna de JavaScript.
Este es el artículo 1 de una serie de 4 partes:
- Nightwatch y llamadas a la API para pruebas «full stack» limpias, rigurosas y aisladas
- Gulp, AWS y Terraform para una entrega continua sin complicaciones
- Circle CI y Saucelabs para automatizarlo todo
Nuestra configuración resultaba especialmente complicada porque contamos con varios servicios de backend totalmente independientes y dos aplicaciones React que comparten gran parte del código. Si te estás enfrentando a una situación similar, espero que esta serie te ahorre algunos pasos.
Nightwatch y llamadas a la API para pruebas «full stack» limpias, rigurosas y aisladas
El objetivo es escribir un conjunto de pruebas que pongan a prueba realmente cómo interactúan las aplicaciones front-end y los servicios back-end. Además, dado que tenemos usuarios en todo el mundo que utilizan Chrome, Firefox e IE en Windows y Mac, queremos asegurarnos de que no se produzcan fallos en ninguna de las combinaciones de navegador, sistema operativo y tamaño de pantalla que nos comprometemos a admitir.
Aquí tienes una vista previa de depuración de lo que ejecutamos mediante CI cada vez que se realiza un push a GitHub, en cada rama:
Nota importante: Las pruebas anteriores se están ejecutando sin simulaciones. Todos los servicios de backend están disponibles para estas pruebas.
Trampa A: He visto a menudo «pruebas de humo» de pila completa escritas para envoltorios de Phantom o Selenium que ejecutan una larga cadena de comandos en serie, cada uno de los cuales se basa en el anterior, iniciando sesión y recorriendo luego el alcance de las funcionalidades de una aplicación para asegurarse de que todo funciona. Cada vez que hay que cambiar o añadir algo, se rompe algo más adelante en la cadena. No, gracias.
Trampa B: Del mismo modo, he visto a ingenieros crear una especie de macros que realizan acciones habituales, y estas acciones se ejecutan repetidamente en el navegador para crear estados habituales. Es eficaz, pero lento, sobre todo si esos pasos implican mucha interfaz de usuario.
En esta ocasión, hemos evitado ambos problemas recurriendo a utilidades de la API para configurar las pruebas exactamente como las necesitamos:
Hay un par de trucos útiles ocultos en estas «Promises» iniciales. La función ` helpers.createTeam ` utiliza nuestra API para crear un nuevo equipo y un nuevo usuario (gracias a faker.js) y, a continuación, utiliza las credenciales generadas para iniciar sesión en Nightwatch…
…y, a continuación, por separado, para obtener un token de API que pueda utilizar en las solicitudes posteriores:
La sencilla función `assign() ` almacena los objetos devueltos para su uso posterior.
Esto significa que , para cada bloque de pruebas, creamos un nuevo equipo y un nuevo usuario, así como todos los objetos de datos que necesitaremos para las pruebas. Puede parecer excesivo, pero ahora contamos con pruebas automatizadas de las que podemos estar seguros de que están aisladas… y esto también significa que se pueden ejecutar en paralelo. Más adelante hablaremos de ello.
Alineación de los objetos de página de Nightwatch con React Router
Los «Nightwatch Page Objects» ponen en práctica una idea que Martin Fowler propuso aquí, según la cual se puede separar el código que se integra en una página determinada de las pruebas que verifican su funcionalidad.
Hemos comprobado que esto resulta fundamental para la reutilización del código de prueba y nos ayuda a pensar de forma lógica sobre la funcionalidad que estamos desarrollando, sobre todo en el caso de funciones que no son triviales.
La ventaja resulta especialmente evidente al revisar una solicitud de incorporación de cambios más extensa. De un solo vistazo, queda bastante claro lo que está pasando:
A continuación, puedes consultar el objeto de página para hacerte una idea de cómo utilizamos la interfaz de usuario para cumplir con los requisitos de las pruebas:
Quizá te hayas dado cuenta de que, para archivar una plantilla, es necesario aceptar un cuadro de diálogo de confirmación de SweetAlert . Tenemos conceptos como los modales y SweetAlert registrados como objetos de página propios de Nightwatch, por lo que tener en cuenta este paso es muy sencillo; además, dado que está integrado en el comando del objeto de página, la prueba no necesita saber que se requiere una confirmación.
Una vez que hayas terminado de revisar las pruebas y los objetos de página, es muy sencillo pasar a ver los componentes de React que implementan el objeto de página y la infraestructura de Redux/Thrift que gestiona lo que necesitan dichos componentes. Si alguna vez se te han nublado los ojos al intentar asimilar una solicitud de incorporación de cambios (PR) extensa, créeme, esto supone un avance increíble.
Dado que React Router nos ofrece una visión tan clara del mapa de nuestro sitio web, podemos asegurarnos de que los objetos de página permanezcan sincronizados con nuestras rutas en ambas aplicaciones, y ya estamos listos para empezar.
Mejora Nightwatch con herramientas avanzadas como la función de arrastrar y soltar
NightwatchJS es un envoltorio de Selenium que ofrece de serie la mayor parte de las funciones de navegación por la interfaz de usuario que necesitamos. Además, te permite insertar scripts para ampliar tus capacidades de prueba.
En nuestra aplicación, hacemos un uso extensivo de lafabulosa biblioteca React DnDde Dan Abramov. Para probarla, Aaron configuró un comando de Nightwatch que envuelve Drag Mock, de Andy Wermke, de la siguiente manera:
Esto nos permite incluir acciones de arrastre en los objetos de la página:
Esto nos ofrece una forma sencilla y semántica de definir los comportamientos de arrastre en las pruebas:
Del mismo modo que el uso de JSX ha permitido que nuestros diseñadores envíen más pull requests de diseño, estas técnicas de pruebas nos permiten incorporar a ingenieros de automatización de control de calidad con poca experiencia para que nos ayuden a escribir pruebas de alta calidad, y los probadores manuales del equipo pueden detectar interpretaciones erróneas de los requisitos en una fase temprana del proceso. Todos salen ganando.
El papel de las pruebas de integración «full stack»
Eso sí, ninguna de estas técnicas elimina la necesidad de contar con unidades sólidas. Utilizamos Mocha para probar los reductores, acciones, etc. de Redux, y Enzyme para probar los componentes de React de forma aislada. Además, consideramos fallida una ejecución de pruebas si el código fuente no supera ESLint.
Pero yo valoro mucho más estas pruebas «full stack», porque nos confirman que, cuando eliminamos los simuladores e integramos todos los servicios de backend, seguimos disponiendo de toda la funcionalidad que prometemos a nuestros usuarios, y no solo en Chrome en una pantalla Cinema Display en Soma, sino en condiciones reales, en un portátil con Vista estropeado que ejecuta IE11 en una plataforma petrolífera. Ahí es donde nuestro software tiene que dar la talla, y Nightwatch nos ayuda a tener la seguridad de que lo conseguimos.











