Video Summary and Transcription
El diseño impulsado por pruebas de componentes Cypress puede llevar a los ingenieros front-end al siguiente nivel al cubrir ejemplos de TDD, pruebas de componentes, pruebas de punto final y las mejores prácticas recomendadas. El flujo de TDD implica comenzar con pruebas fallidas, hacer que funcionen y luego mejorarlas. Las pruebas de componentes se pueden escribir de forma incremental, utilizando envoltorios y props personalizados. Las diferencias entre React Testing Library y Cypress Component Test radican en el estilo de la API. Se puede lograr cobertura de código con pruebas de componentes Cypress, y se puede utilizar el adaptador Pack.js Cypress para evitar la duplicación de pruebas entre el backend y el frontend.
1. Introducción a Cypress Component TDD
Hola, soy Burat, un ingeniero de personal y arquitecto de pruebas en Xtent. El diseño impulsado por pruebas de componentes de Cypress puede llevar a nuestro ingeniero de front-end al siguiente nivel. Cubriremos ejemplos de TDD, pruebas de componentes, pruebas de punto final y las mejores prácticas recomendadas. La aplicación bajo prueba es una versión de React de dos reseñas de Angular. Tenemos una aplicación de React con un servidor JSON y muchos ejemplos de pruebas de componentes de Cypress. Comenzaremos con una prueba de marcador de posición, aseguraremos la representación y los estilos, y luego escribiremos una prueba fallida para un atributo de enlace.
Hola a todos. Mi nombre es Burat. Soy un ingeniero de personal y arquitecto de pruebas en Xtent. Y creo que el diseño impulsado por pruebas de componentes de Cypress puede llevar a nuestro ingeniero de front-end al siguiente nivel.
Hablaremos sobre un ejemplo de TDD y pasaremos por nuestra prueba de componente. Hablaremos más sobre las pruebas de componentes, un segundo ejemplo. Cubriremos las pruebas de punto final dentro del contexto de TDD. Y finalmente, concluiremos con las mejores prácticas recomendadas.
La aplicación en prueba son dos reseñas de Angular. Todos ustedes están familiarizados con ella. Está reescrita en React. Y el libro, Diseño impulsado por pruebas de componentes de Cypress. Podrán encontrar el enlace al libro aquí mismo. Y la aplicación final con todo el código fuente, todo en esta presentación, en este enlace.
Es una aplicación de React con un servidor JSON, algunas herramientas interesantes. Tenemos muchos ejemplos de pruebas de componentes de Cypress aquí. Cada uno de ellos tiene un espejo de la biblioteca de pruebas de React. Tenemos pruebas de integración de UI, simulando la red. Tenemos pruebas de extremo a extremo de API y UI. La proporción de ellos es de uno a cinco a quince, lo que le da una idea sobre la arquitectura de pruebas.
Aquí está nuestro primer componente. Lo encontrarán en el Capítulo 3 del libro, nuestro código final aquí mismo en este enlace. Comenzamos con una prueba de marcador de posición. Primero, queremos asegurarnos de que podamos renderizar algo, importamos el archivo correcto, tenemos los estilos. Este es un buen punto de partida de referencia. Pueden simplemente copiar y pegar esto en cada ejecución de prueba de componente de inicio. Así que tienen eso siendo renderizado. Genial. Escriban una prueba fallida porque con TDD, tienen pruebas de detección de fallas para cosas que importan. Queremos un enlace que tenga un atributo que vaya a reactjs.org.
2. Diseño y Mejoras de Pruebas de Componentes
Tenemos nuestro primer fallo. Intentamos hacerlo funcionar agregando un enlace con un href. Las pruebas de componentes pueden ayudar en los ciclos de refactorización rojo-verde. Agregamos una prueba fallida para asegurar la visibilidad y luego agregamos un ícono para una mejor representación.
Y tenemos nuestro primer fallo. Genial, una pequeña prueba, fallando, y tratamos de hacer que funcione, agregando un enlace con un href. Una vez que eso era algo que fallaba, queremos hacer lo mínimo para que funcione, y luego simplemente queremos intentar mejorarlo. Queremos usar las pruebas de componentes como la herramienta de design para ayudar en los ciclos de refactorización rojo-verde.
No estamos viendo nada que se esté representando, así que pensamos, bueno, aquí hay una idea, asegurémonos de que esto sea visible. Así que agregamos una prueba fallida, ahora tenemos un rojo. Las mejoras incrementales de visión significan que puedes usar la retroalimentación visual que no cumple tus expectativas como indicador rojo. Entonces, si no lo veo, quiero algo ahí. Voy a agregar un ícono, para ver una representación decente. Que algo sea visible realmente no ayuda, pero quiero ver lo correcto.
3. Writing Incremental Tests and Custom Wrappers
Lo obvio pero difícil de hacer con TDD es escribir pruebas incrementales muy pequeñas a la vez. Quieres construir el componente de forma iterativa usando pruebas. Al final pensamos, okay, tal vez necesitemos un ícono al hacer este componente. Si tienes TypeScript y ESLint, tiene herramientas que también pueden ayudar en tus ciclos de refactorización rojo-verde. Pero podemos simplemente agregar ese atributo ahí mismo. Para que la prueba funcione, además de eso, tenemos que envolverlo con browser-router porque así es como montas tu componente cuando estás usando react-router-dump, simplemente lo envuelves con browser-router. Siempre debes recordar que una prueba de componente es una aplicación a pequeña escala. No hay problema, puedes escribir una función de envoltura personalizada. Volviendo a la prueba, quieres agregar un enlace que tenga tres spans con algunas cadenas. Entonces, escribe una prueba fallida para eso.
Lo obvio pero difícil de hacer con TDD es escribir pruebas incrementales muy pequeñas a la vez. Quieres construir el componente de forma iterativa usando pruebas. Quieres descubrir más sobre ello con la prueba, como si estuvieras improvisando, pero a medida que improvisas, avanzas y agregas un paso.
Entonces tenemos un atributo, agregamos una prueba para ello, y luego agregamos esa comprobación de atributo. Escribimos otro paso de prueba y luego agregamos otro atributo para que funcione. Al final pensamos, okay, tal vez necesitemos un ícono al hacer este componente. Agregamos ese selector de tamaño de datos a la etiqueta superior del componente, lo cual recomiendo porque hace que el componente sea muy fácil de encontrar cuando se usa como hijo o en pruebas de extremo a extremo. Así que hacemos eso, y luego debajo de ese componente, esperamos que se renderice un .sdg porque ese es el ícono que estamos buscando.
Si tienes TypeScript y ESLint, tiene herramientas que también pueden ayudar en tus ciclos de refactorización rojo-verde. Aquí, falta la propiedad 2. NavLink es de react-router-dump. Así que realmente no tenemos que tener una prueba fallida para ello. Pero podemos simplemente agregar ese atributo ahí mismo. Para que la prueba funcione, además de eso, tenemos que envolverlo con browser-router porque así es como montas tu componente cuando estás usando react-router-dump, simplemente lo envuelves con browser-router. Siempre debes recordar que una prueba de componente es una aplicación a pequeña escala. Así que debes replicar las envolturas de tu aplicación. Estás usando browser-router en la aplicación principal. Y estarás usando browser-router cada vez que montes tu componente.
Pero tu aplicación puede verse así. Y tus montajes de prueba se verán como el de la izquierda. No hay problema, puedes escribir una función de envoltura personalizada. Podrás encontrar el enlace aquí y también lo escribirás en el libro. Y es solo una vez. Si algunos de tus componentes no necesitan ser envueltos con algunos de estos, está perfectamente bien. Las envolturas adicionales no cambian realmente cómo se comporta el componente. El componente simplemente usa lo que necesita. Es exactamente lo mismo que harías con la biblioteca de pruebas de React. También puedes escribir diferentes tipos de envolturas personalizadas, ¿verdad? Algunas envolturas para estos componentes, pero una envoltura diferente para otro conjunto de componentes. Volviendo a la prueba, quieres agregar un enlace que tenga tres spans con algunas cadenas. Entonces, escribe una prueba fallida para eso.
4. Test Failure and Test Design Comparison
Nos encontramos con un fallo debido a la falta de un selector de datos del enlace de navegación, que luego se agrega junto con clases para mejorar la representación. La prueba pasa y se representa como se espera. Surge la pregunta: ¿deberían descomponerse las pruebas o mantenerse como un flujo único? El lado derecho, con un flujo único, es preferible si el estado inicial es común. Sin embargo, siempre que las pruebas no se dupliquen y sean independientes del orden y sin estado, ambos enfoques son aceptables. Se realiza una comparación con la biblioteca de pruebas de React, donde la intención sigue siendo la misma pero el estilo de API difiere.
Y luego obtenemos nuestro fallo. Porque ni siquiera tenemos ese selector de datos del enlace de navegación. Así que procedemos a agregar eso. Agregamos algunas clases para que la representación se vea bien. Ahí están nuestros spans. Cada uno de ellos tiene un texto codificado en duro. Y tenemos una prueba que pasa al final. Se representa como queremos.
Surge la pregunta, ¿debemos descomponer las pruebas o no? En el lado izquierdo y derecho, es la misma prueba exacta y lo mismo. El lado izquierdo lo descompone, el lado derecho solo realiza un flujo. Lo que importa es el estado inicial de una prueba. Si alcanzar este estado es común, entonces, en mi opinión, el lado derecho, una oportunidad para una mejora de la prueba es más fuerte. Prefiero el ejemplo de la derecha. Siempre que las pruebas no se dupliquen, sean independientes del orden y sin estado, ambos lados están bien. La razón por la que los probadores de unidades pueden preferir el lado izquierdo es porque quieren tener un radio de explosión más pequeño. Esto no es un problema. Si tienes un ejecutor de pruebas de Cypress, es muy fácil encontrar exactamente dónde ocurrió el fallo. Solo tienes que tener cuidado de no hacer lo del lado izquierdo.
Entonces aquí tenemos tres bloques de borde, se superponen entre sí. Entonces, el primero está cubierto en el segundo y el tercero cubre el segundo. Así que esto es solo una prueba. Podemos escribir solo una prueba, la mayoría del tercer bloque en la comprobación de visibilidad desde la primera prueba, y eso es suficiente. Un ejemplo de qué hacer y qué no hacer. Aquí está la comparación con una biblioteca de pruebas de React. Uno a uno, es lo mismo. Puedes traducir cada línea. La intención siempre es la misma. La diferencia está en el estilo de la API. Así que tienes Async, Await, asignaciones de variables en un lado, y tienes una sintaxis de cadena, un poco más de flujo en el lado derecho. Pero la intención, tus acciones, lo que sea que estés haciendo, es lo mismo.
5. Component Testing with Props and Wrappers
Solo diferentes formas de hacerlo. Tendremos un segundo ejemplo y más puntos sobre las pruebas de componentes, especialmente sobre props, envoltorios de componentes y relaciones padre-hijo. Puedes manipular tu componente tanto con props como con envoltorios. Puedes pasar datos con props, ya sea agregando una prop al componente o usando un envoltorio. Al agregar props, añades la propiedad a los tipos de componente, la añades a los argumentos del componente y la usas en el componente. Esta vez, estamos agregando la propiedad de valor y una prueba fallida para ella. También escribimos una prueba fallida para que un formulario sea de solo lectura y agregamos la prop correspondiente. Cuando te encuentres con fallos, es preferible añadir más pruebas o refactorizar en lugar de añadir código fuente adicional.
Solo diferentes formas de hacerlo. Así que eso fue un recorrido de ejemplo de TDD con pruebas de componentes. Ahora tendremos un segundo ejemplo y algunos puntos más sobre las pruebas de componentes, especialmente sobre props, envoltorios de componentes y relaciones padre-hijo.
Este ejemplo es del capítulo cinco del libro, y aquí está el código final. Puedes usar codificación en duro inicialmente, o puedes usar console.log para que tu prueba pase. Solo codificación en duro, todo está bien ahí. Luego manipulas tu componente ya sea con props o envoltorios.
Así que aquí tenemos una prop. En lugar de una prueba codificada en duro, estamos agregando esa prop aquí mismo, el marcador de posición. Y luego lo agregamos al componente. Puedes pasar datos con props. Como aquí, tenemos una prop para héroes, pasamos un array vacío. Y luego aquí, pasamos un array de héroes. En el lado derecho, en la parte superior, no pasamos nada, solo el componente por sí mismo. Pero si quisieras, podrías tener un envoltorio allí, por ejemplo, Context API, y así proporcionar un valor allí, el array de villanos. Y así es como manipulamos nuestros componentes. Así que puedes usar una propiedad o un envoltorio. Así es como personalizas las pruebas de tus componentes en Cypress, React y cualquier otro lugar. Al agregar props, añades la propiedad, aquí mismo estamos agregando la propiedad de nombre, y luego añades la prop a los tipos de componente. La añades a los argumentos del componente, luego la usas en el componente. El mismo flujo, lo seguiremos. Esta vez estamos agregando la propiedad de valor, ¿una prueba fallida con eso, verdad? Y luego añadimos la prop, el argumento, y la usamos en la prueba misma, que está en el componente. Y en algún momento tenemos una bonita representación, que usaremos para un formulario. Queremos que este formulario también tenga la capacidad de ser de solo lectura. Así que escribimos una prueba fallida para eso, adelante y añadimos la prop. Y si tenemos eventos, simplemente los iniciamos. Aquí tenemos un evento que son dos pulsaciones de tecla, así que queremos que el evento de cambio se llame dos veces. Primero, las pruebas fallidas, y luego añadimos la prop, los argumentos, y de nuevo, la usamos en el componente. Cuando veo fallos en las pruebas, y cuando tienes pruebas verdes, es preferible añadir más pruebas o refactorizar en lugar de añadir código fuente adicional. Esto es muy importante.
6. Diseño de Pruebas y Ejemplo de Relación Padre-Hijo
A veces tenemos una prueba que pasa y luego agregamos mucho código fuente, no es necesario hacer eso. Un poco de prueba, hacerla funcionar, mejorarla. Aquí hay un ejemplo de relación padre-hijo. Siempre verifica si estás duplicando el esfuerzo de prueba que ya se ha cubierto en otro lugar. Queremos encontrar oportunidades para cubrir diferentes funcionalidades. Con JSX y literales de plantilla, puedes ser bastante creativo con tus selectores.
A veces tenemos una prueba que pasa y luego agregamos mucho código fuente, no es necesario hacer eso. Un poco de prueba, hacerla funcionar, mejorarla. Si tienes algo que funciona, es preferible agregar más pruebas, tener un fallo primero o refactorizar antes de ir al código fuente.
Aquí hay un ejemplo de relación padre-hijo. Así que este es un hijo que se utiliza en el padre, dos variedades diferentes, un nombre y una descripción. Siempre verifica si estás duplicando el esfuerzo de prueba que ya se ha cubierto en otro lugar. Queremos encontrar oportunidades para cubrir diferentes funcionalidades. A la derecha, ya tenemos una comprobación de que estamos escribiendo algo y luego esa cosa es visible. Estamos duplicando esa prueba aquí en el padre, y eso no es bueno. En el padre, puedes hacer algo más. Podemos comprobar que el padre renderiza dos variantes del hijo. Aquí hay otro consejo, con JSX y literales de plantilla, puedes ser bastante creativo con tus selectores. Me gusta tener un conjunto de datos en la etiqueta superior del componente y si hay alguna variante, simplemente exploto JSX y literales de plantilla, y es bastante divertido.
7. React Testing Library vs Cypress Component Test
React Testing Library versus Cypress Component Test. La diferencia principal está en cómo hacemos la prueba del evento onChange. Las pruebas de punto final son excelentes cuando has terminado de construir tus componentes. Quieres ayudar a la prueba al nivel más bajo y luego avanzar cuando no puedas probar con confianza. Este es un ejemplo de eso. Cómo hacer una característica con ejemplos de TDD. Siempre quieres recordar lo que estás haciendo en tus componentes secundarios. El flujo de TDD es exactamente el mismo con E3. Comienzas con algo que falla, haces lo mínimo para que funcione y luego, si puedes mejorarlo, haces refactorización. Una vez que las cosas funcionan, es preferible agregar más fallos.
React Testing Library versus Cypress Component Test. La diferencia principal está en cómo hacemos la prueba del evento onChange. En el lado derecho está CyGet, la etiqueta de cambio aquí, y luego verificamos la cantidad de llamadas, y en el lado izquierdo, suggest-fn, en lugar de un sitio stub, y verificamos que se haya llamado tantas veces. Haciendo exactamente lo mismo, cada paso se traduce en un estilo ligeramente diferente.
Recorrimos un ejemplo de TDD, un ejemplo de componente, dos ejemplos de pruebas de componentes, algunas mejores prácticas allí. Ahora veamos TDD con pruebas de punto final. Las pruebas de punto final son excelentes cuando has terminado de construir tus componentes. Ahora es el momento de enrutamiento, gestión de estado, flujos de aplicación, componentes que se comunican entre sí o con el backend. Ahí es donde entra E3. Pero recuerda, quieres ayudar a la prueba al nivel más bajo y luego avanzar cuando no puedas probar con confianza. Este es un ejemplo de eso. No puedo hacer nada con el enrutamiento cuando estoy trabajando con componentes. Necesito una prueba de punto final. Primero, miras al hijo. ¿Puedo hacer esto en el hijo? No, y pasas al padre. Si eso no es suficiente, tienes una prueba de integración de UI, donde simulas la red, pero tus componentes se comunican entre sí y tal vez necesites el backend. Tal vez puedas usar pruebas de punto final en ese caso.
Cómo hacer una característica con ejemplos de TDD. Esta es una prueba de punto final. Estamos usando TDD. Es del capítulo 13 y es el código final de esta prueba. Siempre quieres recordar lo que estás haciendo en tus componentes secundarios. Así que aquí estamos visitando el componente, visitando la aplicación y una prueba de punto final, y nos aseguramos de que se muestre el componente de la barra de encabezado. ¿Cómo modificamos nuestra aplicación para que se muestre el componente de la barra de encabezado? Vamos y echamos un vistazo al hijo, la barra de encabezado, y allí estamos usando el enrutador del navegador y envolviendo la barra de encabezado, por lo que nuestra aplicación también tendrá que hacer eso. Puedes hacer trampa y siempre mirar la prueba de componente que ya construiste. Te facilitarán la vida cuando escribas tu prueba de punto final o cuando escribas otras pruebas de componentes. Ya tendrás los selectores allí, selectores de tamaño de datos, y siempre puedes consultarlos, es documentación para ti, ¿qué hago con esto? El flujo de TDD es exactamente el mismo con E3. Quieres comenzar con algo que falle, hacer lo mínimo para que funcione, así que es mínimo en el componente de la barra de navegación, y luego, si puedes mejorarlo, hacer refactorización. Una vez que las cosas funcionan, es preferible agregar más fallos.
8. Not Found Route and Best Practices
Quieres tener una ruta de no encontrada y mostrar un componente de no encontrada. Agrega una prueba que falle, luego agrega el componente de no encontrada y haz la configuración de la ruta. Busca fallos y sigue agregando pruebas hasta que haya un fallo. En un ejemplo de TDD utilizando pruebas de punto final para el enrutamiento, visita la ruta del héroe y asegúrate de que se muestre el componente del héroe. Sigue las mejores prácticas recomendadas para las pruebas de punto final de la API, como usar un cliente de prueba de API en lugar de un cliente de UI, estar al tanto de los conjuntos de pruebas, evitar la duplicación y usar cantidades moderadas de pruebas de punto final.
y eso debería mostrar un componente de no encontrada, ¿verdad? Primero la prueba que falla, y luego agregamos ese componente de no encontrada, hacemos la configuración de la ruta, y estamos descubriendo más sobre la aplicación a través de las pruebas de esta manera. Si tenemos pruebas que pasan, queremos agregar pruebas o refactorizar antes de agregar más código fuente.
Tenemos una prueba que pasa. Agregamos esa verificación adicional para la ubicación, todavía estamos en verde. Entonces, bien, luego podemos pensar en otro fallo. Queremos buscar estos fallos. Los fallos son geniales cuando estás haciendo TDD. Quieres seguir agregando pruebas hasta que haya un fallo. Así que eso es muy bueno. Una vez que tenemos esa prueba que falla, luego puedes agregar la nueva característica. Así que aquí estamos visitando la ruta del héroe, y queremos que se muestre el componente del héroe. Ese es nuestro fallo. Para hacer que las cosas funcionen, simplemente agregamos esa característica. Decimos, bien, agregamos los héroes, deberíamos estar renderizando ese cierto componente. Y ese es un ejemplo de TDD utilizando pruebas de punto final para el enrutamiento.
Repasemos las mejores prácticas recomendadas. Hay algunas de estas, así que las repasaremos todas. Con las pruebas de punto final de la API, no hagas pruebas de punto final de UI ingenuas antes de tener confianza en que tu backend funciona. Quieres usar un cliente de prueba de API en lugar de usar tu cliente de UI como el cliente de prueba. De esta manera, puedes probar más temprano en tus implementaciones. Quieres estar al tanto de los conjuntos de pruebas de tu backend, y quieres evitar la duplicación. Quieres usar cantidades moderadas de pruebas de punto final y hacer un relleno de brechas dirigido cuando tienes una prueba de punto final de UI. Ahora no quieres tener que repetir esta prueba de punto final de UI si ya tienes confianza en una área. Primero, esta prueba de inicio de sesión funciona. Ahora intenta no hacer el mismo inicio de sesión en cada prueba. Tal vez puedas entrar por la puerta trasera o tener otra forma de iniciar sesión. Cuando el inicio de sesión no funciona, solo una prueba va a fallar. Y sabes que no está funcionando. No todo tiene que fallar. Aquí tienes tu estrategia de prueba de punto final de API para CRUD.
9. API and UI End-to-End Testing
Entonces es creación, crear y eliminar, actualizar, crear, actualizar y eliminar. La actualización cubre todos los flujos. Este es el ejemplo del backend. Agregamos un héroe, nos aseguramos de que se agregue, lo actualizamos, nos aseguramos de que se actualice correctamente, lo eliminamos y verificamos que se elimine de la base de datos. Las pruebas de extremo a extremo de la interfaz de usuario son similares a las pruebas de extremo a extremo de la API, pero puedes usar los comandos de la API y aislar las pruebas de la interfaz de usuario. Comienza con la creación de la interfaz de usuario y luego realiza la limpieza con la API. La prueba de integración de la interfaz de usuario incluye cancelar, actualizar y agregar un héroe a la lista.
actualizar, crear, actualizar y eliminar. Y para poder eliminar, tienes que crear algo. Pero mira esto. La actualización cubre todos los flujos. Si pruebas la actualización, la creación y la eliminación ya están cubiertas. Así que solo prueba la actualización. Este es el ejemplo del backend. Puedes encontrarlo en el Capítulo 15 y el código final aquí en este enlace.
Estamos agregando un héroe, una solicitud de publicación. Nos aseguramos de que esa cosa se haya agregado. Haz una afirmación. Luego seguimos y lo editamos, lo actualizamos. Y luego nos aseguramos de que lo que actualizamos se haya actualizado de la manera que queríamos. Luego hacemos la eliminación y luego nos aseguramos de que se elimine de la base de datos. Este es el ejemplo de nuestra prueba de extremo a extremo de la API. Y quieres tener esto donde el código del backend vive más cerca allí si es posible.
La prueba de extremo a extremo de la interfaz de usuario por otro lado es muy similar a la prueba de extremo a extremo de la API. Pero en cambio puedes usar los comandos de la API que ya has creado y aislar las pruebas de la interfaz de usuario. Por ejemplo, si quieres probar la actualización, puedes ver la base de datos mediante el comando de la API que ya hemos escrito. Puedes hacer tus pruebas de la interfaz de usuario. Y luego al final, puedes eliminar. Pasaremos por el ejemplo de creación simple, pero entiendes la idea. Así que primero haremos la creación de la interfaz de usuario. Y luego haremos la limpieza con la API. Aquí está esa prueba. También pasaremos por la prueba de integración de la interfaz de usuario. Las primeras son cancelar y actualizar. Y realmente no están utilizando la red real. La última es seguir adelante y agregar un héroe. Y después de agregarlo, nos aseguramos de que el héroe esté en la lista. Puedes encontrar la prueba completa aquí.
10. Final End-to-End Test and Test Design
En el capítulo 17, navegamos hasta el héroe, nos aseguramos de que todo esté resuelto, creamos la interfaz de usuario, hacemos afirmaciones y realizamos eliminaciones de la API. Cada paso requiere un desarrollo cuidadoso. Mantén las pruebas de extremo a extremo pequeñas cuando hagas TDD.
En el capítulo 17, pasamos por esto en el capítulo de consulta de React. Y aquí está la prueba final. Al principio, simplemente navegamos hasta ese héroe. Queremos que todo se resuelva. Estamos utilizando la red real, no hay simulación aquí. Estamos en la ubicación correcta. Hicimos la creación de la interfaz de usuario. Así que completamos los detalles, presionamos el botón Guardar. Y luego hacemos nuestras afirmaciones de que estamos en el camino correcto, que hemos agregado esto que se muestra allí. Y finalmente, realizamos las eliminaciones de la API, como vimos antes. Lo que debes tener en cuenta es que cada uno de estos pasos puede requerir mucho desarrollo. Por lo tanto, con las pruebas de extremo a extremo de la API donde estás haciendo TDD, no quieres hacerlas aún más pequeñas porque una línea de prueba de extremo a extremo puede cubrir mucho código fuente. Esta es la idea principal a partir de aquí. Mantén las pruebas de extremo a extremo aún más pequeñas cuando estés haciendo TDD.
11. UI Integration Testing and Error Cases
¿Qué es una prueba de integración de UI? Solo utiliza pruebas reales de extremo a extremo cuando sea necesario. Evita duplicar pruebas y aprovecha la funcionalidad del backend. Convierte las pruebas de extremo a extremo de UI en pruebas de integración de UI. Prueba la actualización y cancelación utilizando la red real. Utiliza datos simulados en lugar de hacer solicitudes reales. Prueba casos de error y flujos positivos a nivel de componente. Evita probar detalles de implementación y concéntrate en las pruebas de caja negra.
¿Qué es una prueba de integración de UI? Por lo tanto, siempre debes evaluar si necesitas tu backend para tener confianza en la funcionalidad de tus aplicaciones. Solo utiliza pruebas reales de extremo a extremo cuando sea necesario tener esta confianza. Y no deberías tener que repetir esas costosas pruebas de extremo a extremo en todas partes. Ten en cuenta lo que ya está haciendo tu backend y eso hace que tus preocupaciones de extremo a extremo de UI sean aún menores.
Ten cuidado de no duplicar y trata de obtenerlas. Puedes juzgar a las personas por lo que no hacen, por el costo de las cosas en las que no profundizan. Esto es especialmente cierto para los ingenieros que se llaman a sí mismos compradores de una cadena. Convierte una prueba de extremo a extremo de UI en una prueba de integración de UI. Aquí tenemos dos pruebas. Una de ellas prueba la actualización, la otra prueba la cancelación. Utilizando la red real, simplemente esperamos a que la red se estabilice antes de continuar y comprobamos que el botón de actualización o cancelación funcione correctamente. Solo tienes una prueba de extremo a extremo que agrega un héroe y verifica que la lista se actualice. Por lo tanto, no necesitamos realmente esta solicitud GET real. Puede ser solo datos simulados. Si usamos un archivo JSON, cada vez que accedas a esa ruta en lugar de la cosa real, utiliza el archivo y ahí tienes tus datos. Para poder probar la actualización o cancelación con confianza, no necesitas el backend. Es un caso de uso perfecto para la prueba de integración de UI.
Cuando tienes errores, quieres probar tus casos de error. Cualquier prueba que cubra el flujo positivo o una intercepción lateral es un buen punto de ramificación. Intenta probar a nivel de componente. Y si no puedes probar algo, un caso de error negativo, y estás allí, debes pasar a la prueba de integración de UI. Aquí, este es nuestro escenario positivo. Presionas el botón Guardar y esperamos que se envíe una solicitud POST. Ahí está el lugar perfecto para hacer una prueba de caso de error, un caso que no sea 200. Comenzamos con un 400, también agregamos un retraso y nos aseguramos de que haya un spinner al principio, y luego obtenemos el error. Esto es del capítulo 18, cuando cubrimos suspense, error boundary y concurrencia. Esta prueba por sí sola solo cubre el caso de uso para suspense y error boundary para este componente en particular. Debes evitar probar detalles de implementación. Debes inclinarte más hacia las pruebas de caja negra mientras pruebas tu componente. Y esta es la misma idea de react-testing library, que utiliza max service worker para hacer lo mismo que estamos haciendo con Cypress intercept.
12. Testing Consequences and Visual Feedback
Entonces, en el lado izquierdo, tenemos una prueba de detalle de implementación. Al final, debería realizarse una solicitud de red al backend. Cypress intercept puede hacer las cosas un poco más concisas, un poco más flexibles. Quieres aprovechar la retroalimentación visual de la prueba de componente. Mejora tu TDD, te inspira a verificar más pruebas y te permite detectar estos defectos antes de que incluso ocurran. Es posible hacer pruebas ad hoc en una prueba de componente, por lo que puedes ejecutar la prueba de componente y luego tu componente está ahí por sí solo sin leer ninguna otra parte de la aplicación. Es simplemente una experiencia de otro nivel para un desarrollador cuando trabaja en un componente de forma aislada. Aquí hay una prueba final para Navbar, RTL versus prueba de componente de Cypress. Cypress puede ser más corto a veces, menos código debido a todos los otros paquetes en comparación con jQuery que viene con él, por lo que es más fácil deseleccionar o obtener los que no están seleccionados en comparación con la otra API en la biblioteca de pruebas de React. Es la misma forma de hacer lo mismo.
Entonces, en el lado izquierdo, tenemos una prueba de detalle de implementación. Estamos probando que se llame a 'useState'. O que se llame a 'react-query'. O que se llame a nuestro gancho personalizado cuando hacemos clic en el botón Guardar. En cambio, quieres probar las consecuencias de hacer clic en el botón Guardar. Al final, debería realizarse una solicitud de red al backend. Y es mejor que verifiques esto porque si cambias tu implementación, esta prueba seguirá funcionando. No importa realmente cómo hacemos los detalles internos. Max service worker y Cypress intercept son muy comparables. Aquí está mi comparación. Puedes verificar los enlaces. En mi opinión, Cypress intercept puede hacer las cosas un poco más concisas, un poco más flexibles. Pero haz tu propia investigación y déjame saber qué piensas.
Quieres aprovechar la retroalimentación visual de la prueba de componente. Entonces, aquí en el capítulo ocho, NAVVAR, estoy escribiendo el libro y pensé que esta es una buena prueba. Pero cuando inicio el componente, veo que cada enlace está resaltado. De acuerdo, hago clic en cada uno, voy al enlace correcto. Bien, pero hay un defecto. Esto significa que visualmente, cuando ves el componente, esta calidad de retroalimentación mejora tu TDD, te inspira a verificar más pruebas y te permite detectar estos defectos antes de que incluso ocurran. Obtienes esa retroalimentación de la herramienta CLI, pero debes tener mucho cuidado. Para mí, fue mucho más fácil ver la cosa visual y pensar, bueno, cuando simplemente hago clic en algo, solo ese elemento debería estar resaltado y el resto no debería estar resaltado. Así que agregué una prueba para eso. La mejor parte es que es posible hacer pruebas ad hoc en una prueba de componente, por lo que puedes ejecutar la prueba de componente y luego tu componente está ahí por sí solo sin leer ninguna otra parte de la aplicación. Puedes hacer clic y explorar, ver las herramientas de desarrollo, ver las extensiones. Es simplemente una experiencia de otro nivel para un desarrollador cuando trabaja en un componente de forma aislada. Es simplemente alucinante esta tecnología. Aquí hay una prueba final para Navbar, RTL versus prueba de componente de Cypress. Nuevamente, estilos diferentes, misma intención. Cypress puede ser más corto a veces, menos código debido a todos los otros paquetes en comparación con jQuery que viene con él, por lo que es más fácil deseleccionar o obtener los que no están seleccionados en comparación con la otra API en la biblioteca de pruebas de React. Es la misma forma de hacer lo mismo.
Using Wallaby for TDD and Combined Coverage
Si no puedes usar herramientas visuales, mi consejo es usar Wallaby. Proporciona retroalimentación en línea para TDD y se puede utilizar desde una herramienta CLI o IDE. La cobertura combinada te permite asegurar el éxito de tu TDD. Una vez que avanzas más allá de los componentes, TDD con pruebas de punto final se vuelve más relevante. La idea clave de TDD es comenzar con algo que falle, hacer lo mínimo para que funcione y luego mejorarlo. Gracias por escuchar. Comencemos la sesión de preguntas y respuestas discutiendo los resultados de la encuesta. Las pruebas de componentes lideraron, pero las pruebas unitarias y de extremo a extremo también fueron populares. Sería interesante ver si estos resultados cambian después de la charla.
Si no puedes usar herramientas visuales, entonces quieres hacer TDD, mi consejo es usar Wallaby. Optaría por esta herramienta cuando estoy probando el backend, especialmente. Pero si no puedes usar herramientas visuales, si es demasiado difícil migrar, echa un vistazo a Wallaby.js. Te dará retroalimentación en línea mientras escribes tu prueba. Y eso es la cúspide del TDD, que puedes tener desde una herramienta CLI o IDE. Si puedes tener elementos visuales, al menos ten eso. Puedes usar la cobertura combinada para asegurarte de que tu TDD fue exitoso. Así que pasa por ese ejemplo en el apéndice del libro. Obtenemos cobertura de las pruebas de componente de Cypress, obtenemos cobertura de las pruebas de punto final de Cypress y obtenemos cobertura de las pruebas de Jest y React Testing Library. Esto significa que realmente no tienes que migrar de React Testing Library a Cypress Component Testing. Ya puedes tener pruebas con Jest, las pruebas antiguas tal vez, o las pruebas que no son de componentes, tal vez estás probando tus reductores o algo así. Simplemente pueden combinar la cobertura. Y al final, acercarse al 100% de cobertura ya no es un desafío. Es muy fácil. He estado haciendo esto en múltiples proyectos con JavaScript o TypeScript, no importa. La cobertura combinada es el camino a seguir. No es una medida definitiva, pero si tienes una cobertura de código del 100%, nadie va a decir que no tienen confianza en su aplicación.
¿Qué hemos aprendido? La calidad de la retroalimentación en las pruebas de componente de Cypress mejora el TDD. Ingeniería de componentes y detección temprana de defectos. Una vez que avanzas a enrutamiento, gestión de estado y otras cosas complejas más allá de los componentes, TDD con pruebas de punto final es más relevante. Con TDD, la idea clave es comenzar con algo que falle, hacer lo mínimo para que funcione y luego intentar mejorarlo. Aquí están los enlaces y referencias, el libro, la aplicación final y la inspiración que contribuyó a este contenido. Muchas gracias por escuchar. Que tengas un buen día. Adiós.
Entonces, sí, comencemos la sesión de preguntas y respuestas discutiendo las respuestas a tu pregunta de la encuesta. Me interesó ver esto, ya que parecen relativamente similares. Obviamente, las pruebas de componentes lideraron con un 43%, pero las pruebas unitarias y de extremo a extremo están muy cerca con un 30% y un 26% respectivamente. ¿Qué opinas de esos resultados? Me gustaría saber si hicimos esta encuesta antes y después de la charla, si estos resultados cambiarán. Sí, creo que a medida que avanzamos, comenzamos a ver realmente algunos de los beneficios que destacaste. Es muy interesante ver cuántas personas han cambiado de opinión debido a eso.
Frameworks de JS y Cobertura de Código
Las diferencias entre los frameworks de JS para las pruebas de componentes de Cypress se encuentran principalmente en la forma en que se montan los componentes. Las pruebas de componentes de React son similares al montaje regular de una aplicación de React, mientras que Angular y Vue tienen sus propias configuraciones específicas. Lograr la cobertura de código con las pruebas de componentes de Cypress depende del framework y del empaquetador utilizados. Cypress permite combinar la cobertura de código entre las pruebas de extremo a extremo y las pruebas unitarias, incluyendo las pruebas de componentes. La migración de otras bibliotecas de pruebas a las pruebas de componentes de Cypress permite combinar las pruebas existentes y mantener una cobertura general. Se recomienda utilizar servicios para la integración de la cobertura de código.
Entonces, vamos a tener algunas preguntas aquí de la audiencia, así que vamos a empezar. La primera pregunta es, ¿cuáles son las diferencias entre los diferentes frameworks de JS para las pruebas de componentes de Cypress? Creo que hay algunas diferencias, ¿verdad? Tienes React, tienes Vue, tienes Angular, tienes Next.js en este momento, y algunos otros que están por venir. Por ejemplo, entre Angular y React, la forma en que se monta el componente es prácticamente la única diferencia. Con las pruebas de componentes de React, será muy similar a cómo se monta tu aplicación regular. Así que si has desarrollado con React antes, estarás muy familiarizado con las pruebas de componentes de Cypress en la variante de React. Pero si has sido un desarrollador de Angular, creo que te gustará aún más porque Karma es conocido por tener muchos boilerplates, y el montaje será, por supuesto, diferente a React, pero te gustará mucho más que montar un componente y configurarlo con boilerplate Karma. Y lo mismo ocurre con Vue. Así que es solo la forma de montar los componentes, el resto es exactamente igual que una prueba de extremo a extremo. Así que si has usado Cypress para pruebas de extremo a extremo, realmente estarás en tu propio juego con las pruebas de componentes de Cypress. Sí, es bueno que puedas aplicar los mismos principios, sin importar qué framework se haya utilizado para desarrollarlo. ¿Tienes alguna pregunta sobre la cobertura de código también? ¿Cómo logras la cobertura de código con las pruebas de componentes de Cypress? Con Jest, viene de serie, ¿verdad? Pero con Cypress, con las pruebas de extremo a extremo, es bastante fácil, algunas extensiones y algunas configuraciones. Con las pruebas de componentes, dependerá de tu framework y de tu empaquetador. Estoy bastante seguro de que veremos algunas recetas, pero si consultas mi libro, es una aplicación de React que utiliza Webpack, así que hay una buena receta de trabajo allí. Será un poco diferente para Beat, o será diferente para Angular, pero espero que obtengamos algunas recetas del equipo de Cypress porque estoy bastante seguro de que la gente querrá tener algo de cobertura de código en este tipo de pruebas de bajo nivel. Sí, la cobertura de código es definitivamente algo que la gente pregunta y quiere tener en cuenta. ¿Sabes si también se puede combinar la cobertura de código de diferentes tipos de pruebas con las pruebas de componentes de Cypress? Absolutamente, Cypress ha estado mostrando la cobertura de código combinada entre las pruebas de extremo a extremo y las pruebas unitarias regulares de cualquier framework. Puedes simplemente agregar las pruebas de componentes a esta mezcla, puedes combinarlas triplemente, así que por supuesto, cuando tienes una prueba unitaria en Jest, por ejemplo, y una prueba de componente de Cypress, al combinarlo con una prueba de extremo a extremo, puedes esperar ver que esos números realmente aumenten, lo que también plantea un gran caso de uso para la migración. Así que si ya tienes pruebas existentes, digamos en React Testing Library, puedes mantenerlas allí y luego, si quieres cambiar a las pruebas de componentes de Cypress, puedes hacer tus nuevas pruebas con Component Test y simplemente combinar la cobertura y tu cobertura general no disminuirá. Es posible que tengas que depender de servicios, porque hacer esto tú mismo en el CI puede no ser muy a prueba de futuro, no es muy fácil, pero hay ejemplos en línea de cómo hacerlo si prefieres hacerlo así. Creo que esa es la forma de hacerlo, los servicios.
Uso de Pack.js Cypress Adapter para evitar la duplicación de pruebas
Para evitar la duplicación de pruebas entre el backend y el frontend, se puede utilizar el adaptador Pack.js Cypress para aprovechar tanto las pruebas de contrato como las pruebas funcionales. Permite probar la integración antes de la implementación, complementando las pruebas de API de extremo a extremo con Cypress. Esto puede ayudar a reducir las pruebas de API de extremo a extremo y crear una arquitectura de pruebas integral. El adaptador se puede utilizar durante la transición a Pack.js.
De acuerdo, genial. Tenemos una pregunta de Marie en el chat. ¿Recomendarías el adaptador Pack.js Cypress como una forma de aprovechar tanto las pruebas de contrato como las pruebas funcionales y evitar la duplicación de pruebas entre el backend y el frontend? Buena pregunta, he pensado mucho en esto y me encanta el vacío que Pack está llenando, porque principalmente te permite probar la integración antes de implementar. Aún no lo hemos implementado, está en nuestros planes hacerlo, pero me imagino que en el futuro, si podemos implementar Pack, sería un complemento interesante para algunas pruebas de API de extremo a extremo con Cypress, y tal vez podamos reducir un poco esas pruebas de API de extremo a extremo si tienes confianza en algunas pruebas de Pack. Y luego eso permitirá hacer pruebas libremente con Pack, y después de implementar, hacer algunas verificaciones puntuales con Cypress de extremo a extremo, y eso será una buena arquitectura de pruebas. Por supuesto, durante esa transición, podemos utilizar el adaptador, ¿verdad? Podemos aprovechar eso. Sí, creo que lo mencionaste cuando hablaste de la tasa de confianza y de comprender la confianza que ya tienes en tus pruebas existentes en todo el stack, y luego poder construir a partir de ahí con lo que aún necesitas. Y luego otro aspecto de las pruebas, la otra pregunta que ha surgido aquí, es si se pueden realizar pruebas visuales de captura de pantalla con las pruebas de componentes, de la misma manera que se puede hacer con las pruebas de extremo a extremo. Absolutamente. Es solo una línea de código. Y creo que será un poco más estable con las pruebas de componentes porque hay menos partes móviles, ¿verdad? Hemos aplicado esto en nuestra propia biblioteca de pruebas de componentes, lo cual fue muy bueno, por ejemplo, para cientos de variedades de un icono y luego simplemente tomas un antes y un después. Ahorros de costos significativos ahí. Sí. Estamos llegando al final del tiempo, pero también quería preguntar. ¿Crees que es tal vez más impactante hacer pruebas visuales de captura de pantalla con las pruebas de componentes en comparación con las pruebas de extremo a extremo debido a esa estabilidad? Simplemente menos costos para una mayor confianza, ¿verdad? Eso es lo que busco en las pruebas todo el tiempo. Absolutamente. Bueno, muchas gracias por estar aquí con nosotros, Murat, para responder estas preguntas. Los asistentes pueden seguir haciendo preguntas en Discord en el canal de Pistas de Producción de Preguntas y Respuestas. Pero sí, muchas gracias de nuevo por estar aquí. Lo apreciamos mucho. Muchas gracias por tenerme. Adiós.
Comments