Video Summary and Transcription
TypeScript es un lenguaje basado en JavaScript utilizado para aplicaciones móviles. Las reglas de prueba incluyen asegurarse de que las pruebas fallen cuando algo sale mal y solo fallen cuando sea necesario. Las pruebas de integración se pueden realizar utilizando herramientas como Cypress y Netflix PolyJS. Las pruebas de regresión visual comparan capturas de pantalla de los cambios y ayudan a prevenir errores visuales. Se recomienda comenzar con pruebas de extremo a extremo y escribir pruebas para los errores encontrados para principiantes.
1. Introducción a TypeScript y Pruebas Front-end
TypeScript es un lenguaje basado en JavaScript utilizado para aplicaciones móviles. Compartiré mi experiencia y hablaré sobre las pruebas front-end, enfatizando la importancia de invertir en los niveles inferiores de la pirámide de detección de errores.
¿Qué es TypeScript? Es un lenguaje basado en JavaScript que está diseñado para aplicaciones móviles. Esto significa que se utiliza tanto en Android como en iOS, para aplicaciones físicas y del mundo real. Puedes crear plantillas para tus propias aplicaciones, y proporcionar tu propio código base para tus propias aplicaciones.
¿Qué has aprendido hasta ahora? La mayor parte de mi carrera, la he pasado trabajando en campañas de corta duración en agencias creativas. Y aunque aprendí mucho allí, había ciertas cosas que no pude aprender allí. Por ejemplo, la mantenibilidad del software, la escalabilidad. Así que cuando me uní a un equipo de desarrollo de productos hace unos dos años y medio, cambié mucho mi actitud hacia el software. De repente, con cientos de miles de usuarios activos mensuales, la calidad de tu entrega se vuelve mucho más importante que la velocidad a la que entregas. Así que lo que he aprendido en los últimos años es de lo que quiero hablar hoy.
Mi nombre es Iris. Soy originaria de Austria, pero me he mudado por toda Europa en los últimos años, y actualmente estoy en Estocolmo, Suecia. Este es mi nombre de usuario en Twitter, por si quieres seguirme o verme quejarme de cosas de vez en cuando. Aunque tengo posiblemente el peor gusto musical de todos, de alguna manera logré conseguir un trabajo en una compañía de música. En caso de que no estés familiarizado con Spotify, somos uno de los servicios de transmisión de audio más grandes del mundo con alrededor de 60 millones de canciones, incluyendo 1.5 millones de títulos de podcasts. Y con casi 300 millones de usuarios, puedes imaginar que cualquier caso extremo que puedas o no puedas imaginar sucederá para muchas personas. Así que hemos tenido nuestra parte de errores extraordinarios y correcciones de errores, como, por ejemplo, en 2009, cuando John arregló el trabajo de factorización de matrices de Eric instalando cortinas en la sala de servidores para que no se sobrecalentaran. Personalmente, no escribo trabajos de factorización de matrices, sino que mi equipo es responsable de los productos Premium Family, Premium for Students, y Premium Duo en el sitio web principal de Spotify.com. Y esos son los pisos que te mostraré hoy. O los errores que te mostraré provienen de estos pisos. Pero hablando de errores, ¿cómo los encontramos en realidad? Esto es lo que llamo la pirámide de detección de errores. Y en los niveles más bajos, tienes pruebas automatizadas y sistemas de tipos, así como pruebas manuales y exploratorias. Todo eso sucede antes de implementar en producción. Después de eso, tenemos sistemas de monitoreo, y al final, también tenemos a nuestros usuarios que se quejan, por ejemplo, en Twitter o a nuestro servicio al cliente. En un mundo ideal, todos nuestros errores se encontrarían en los dos primeros niveles, y se expondrían al usuario la menor cantidad posible de errores. ¿Y cómo nos aseguramos de evitar exponer errores al usuario? Invirtiendo en esos niveles inferiores de la pirámide. Y eso es de lo que quiero hablar hoy. Específicamente, quiero hablar sobre las pruebas front-end, porque por alguna razón, el 36% de los desarrolladores front-end aún no probaban su código en 2019. Y para asegurarnos de que comenzamos bien, permíteme presentar primero algunas reglas básicas en las que me gusta pensar o tener en cuenta cuando escribo mis pruebas. Una buena prueba tiene algunas características. Debe ser legible, escribible, aislada, rápida.
2. Testing Rules and Bug: Parental Control Lock
Las reglas más importantes para las pruebas son: 1) ¿La prueba fallará cuando algo salga mal? 2) ¿La prueba solo fallará cuando algo salga mal? Trata las pruebas como código normal y prueba la interfaz pública. El primer error discutido es la falta de actualización del bloqueo de control parental. Se escribió una prueba unitaria para la función de alternar filtro, que es una función pura que siempre produce la misma salida dadas las mismas entradas. Probar la función implica configurar los datos, definir el resultado esperado, llamar a la función y comparar la salida con el resultado esperado. La prueba debe fallar cuando algo salga mal y solo fallar cuando sea necesario.
Pero las reglas más importantes para mí son las siguientes. En primer lugar, ¿la prueba fallará cuando algo salga mal? Si no falla cuando algo sale mal, ¿cuál es el punto de tener la prueba? Y hay otra pregunta importante que podemos derivar de eso, que es, ¿qué partes pueden salir mal de qué manera? Y podemos usar eso para decidir qué casos de prueba cubrir, qué escenarios probar.
La segunda pregunta es, ¿la prueba solo fallará cuando algo salga mal? Y esto es casi igual de importante, porque las pruebas también son código, y si tenemos que cambiar constantemente nuestras pruebas para que no fallen, en primer lugar, estamos perdiendo mucho tiempo, pero también perdemos mucha confianza en nuestras pruebas. Así que trata tus pruebas como lo haces con tu código normal, hazlo lo más mantenible posible. Y la forma en que lo hacemos es probando la interfaz pública. Entonces, si solo probamos la interfaz pública, podemos asegurarnos de que solo tengamos que actualizar las pruebas si algo realmente necesita ser actualizado en otras partes de la aplicación también.
Y con eso, veamos el primer error. Bloqueo de control parental que no se actualiza. Dentro de nuestra aplicación, tenemos este filtro de música explícita donde los padres pueden permitir o no música explícita para otras personas en el plan. Desafortunadamente, mientras desarrollaba esta función, esto es lo que veía. Se carga y retrocede. ¿Entonces, qué estaba mal? En alguna parte de nuestra aplicación tenemos esta estructura de datos y tenemos esta bandera de permitir música explícita, verdadera o falsa. Desafortunadamente, después de comunicarnos con el backend, esta bandera no se actualizó correctamente. Afortunadamente, esto nunca llegó a producción porque escribí una prueba unitaria para ello. Y las pruebas unitarias son pruebas que cubren o prueban la funcionalidad de una unidad. En este caso, la función de alternar filtro.
La función de alternar filtro simplemente toma un estado antiguo, un ID y devuelve un nuevo estado. Y esta función de alternar filtro es una función pura porque solo tiene dos entradas y una salida. No importa cuántas veces la llames, dado las mismas entradas, siempre producirá la misma salida. Y lo que me encanta de estas funciones puras es que, en primer lugar, son extremadamente fáciles de entender. Son muy simples de entender. Pero también son muy simples de probar, ¿y cómo las pruebas? Bueno, dado la misma entrada, tienes la misma salida, así que puedes darle alguna entrada y afirmar que la salida es algo como aquí. Primero configuramos los datos que queremos pasar, por ejemplo, una matriz de miembros con un usuario que permanecerá igual y otro que se actualizará. Luego configuramos cuál debería ser el resultado esperado. Y ten en cuenta que la bandera allowExplicitMusic se actualiza de falso a verdadero. Luego llamamos a la función y finalmente comparamos la salida del estado después de data.member con los miembros esperados que configuramos antes. Entonces, es hora de hacer nuestras dos preguntas. ¿La prueba fallará cuando algo salga mal? ¡Sí! ¿La prueba solo fallará cuando algo salga mal? A menos que cambie la lógica de negocio, sí, y en ese caso obviamente queremos actualizar la prueba también. Algunos de ustedes pueden estar pensando ahora, pensé que esto era sobre pruebas de interfaz de usuario. Veamos otro error para siempre, un cargador.
3. Bug: Loader instead of Error
Los usuarios veían un cargador indefinidamente en lugar de un mensaje de error debido a un error en la lógica que establece la bandera isLoading. Las pruebas se pueden realizar simulando la página de error o verificando si el texto 'something-went-wrong' está incluido en la página. La elección entre simular y afirmar la salida depende del uso de la página de error. Cuanto menos simulación haya, más cercana será la prueba al mundo real, pero puede ser más difícil identificar las fallas. El siguiente error es que la página de miembros no se abre.
Entonces esto es lo que los usuarios veían en el caso específico durante algún tiempo. Y la razón de eso es que tenemos este componente de página y el error que teníamos ocurría dentro de la lógica que establece la bandera isLoading. Y debido a eso, isLoading nunca se restablecía, pero había un error en la página. Pero en lugar de mostrar ese error, simplemente mostrábamos este cargador para siempre y siempre y siempre.
¿Cómo se prueba algo así? Bueno, si volvemos a nuestra función de alternar filtro, nuestra función pura de la que hablamos antes, resulta que los componentes React no se ven tan diferentes. Tenemos un componente que recibe props y devuelve un elemento React. Así que deberíamos poder hacer algo como esto. Renderizamos una página y esperamos que el resultado sea algo. Podríamos, por ejemplo, usar Anson para esto. Y en este caso, estamos simulando la página de error. Eso significa que estamos reemplazando la página de error por una falsa que sabrá cuándo ha sido llamada y con qué. En este caso, queríamos afirmar que se ha llamado con el error como propiedad.
¿Esta prueba fallará si algo sale mal? Si no usamos un sistema de tipos adecuado, las props de la página de error podrían cambiar sin que la prueba falle, así que eso no es ideal. ¿La prueba solo fallará cuando algo salga mal? Nuevamente, depende un poco de cómo rendericemos el componente de página de error de manera diferente. Digamos que usas un componente de error diferente en el interior, aunque nada cambiará para el usuario, la prueba fallará. También hay otra forma de probar este componente, que se acerca un poco a lo que haría un usuario si verificara que esto funciona. En este caso, estamos probando si el texto 'something-went-wrong' está incluido en esa página, y estamos usando React Testing Library para esto. ¿Esta prueba fallará cuando algo salga mal? En su mayoría, sí. Hablando estrictamente, algo más también podría fallar en la renderización de esta página y la prueba seguiría siendo correcta, lo cual aún pasaría, pero para el usuario no importa realmente si el error proviene de esto o de otra cosa, el resultado será correcto. ¿La prueba solo fallará cuando algo salga mal? Nuevamente, depende un poco. Si cambiamos la forma en que se renderiza el error, si cambiamos el texto, etc., entonces la prueba podría fallar, aunque en realidad no haya fallado.
Ahora, la pregunta es, ¿debemos simular o no? ¿Cuál es preferible? Y realmente depende. Si tu página de error, por ejemplo, es un componente que usas en todas partes de tu aplicación, entonces creo que es justo asumir que si has llamado a la página de error, todo debería estar bien. Si, sin embargo, consideras que la página de error es un poco más una preocupación interna de ese componente de página, tal vez sea mejor afirmar que el resultado o la salida para el usuario es correcta, así que elige esa opción. En general, cuanto menos simulación haya, más cercana será la prueba al mundo real. Por otro lado, podría ser más difícil descubrir qué está fallando si algo falla. Cuando tengas dudas, siempre pregúntate cómo puedes escribir una prueba que atrape los errores, pero que no tengas que actualizar constantemente. Y con eso, podemos pasar al siguiente error, la página de miembros que no se abre.
4. Integration Testing and Cypress
Me encontré con un problema debido a pasar la función incorrecta, pero lo solucioné a través de una prueba de integración. Las pruebas de integración son pruebas de alto nivel que renderizan páginas completas y simulan respuestas de API. Estas pruebas fallarán cuando algo salga mal en el front-end y se pueden sincronizar con el back-end utilizando herramientas como Netflix PolyJS. Otra tecnología para pruebas similares es Cypress, que realiza pruebas directamente en el navegador e intercepta las llamadas a la API.
En algún lugar estaba pasando la función incorrecta, y debido a eso, las cosas simplemente no estaban sucediendo. Sin embargo, porque antes de comenzar a refactorizar, escribí una prueba de integración, detecté ese problema de inmediato y supe que no había regresiones.
Entonces, ¿qué es una prueba de integración? Una prueba de integración es algo así como las pruebas unitarias que vimos antes, pero prueba varias unidades en conjunto. Algunas personas podrían argumentar que la prueba unitaria que vimos antes ya estaba probando tanto la página de error como el componente de página y ya debería ser una prueba de integración. Nos gusta poner nuestras pruebas de integración a un nivel un poco más alto. Entonces, en lugar de simplemente renderizar un componente, generalmente renderizamos una página completa. La única parte que todavía queremos simular o reemplazar con un objeto falso es la respuesta de la API. Eso es lo que estamos haciendo aquí. Estamos configurando un plan falso. En este caso, un plan familiar. Esto será devuelto por la API más adelante. Luego renderizamos nuestra aplicación en una URL específica. Esperamos a que aparezca la página de administrar tu plan familiar. Luego hacemos clic en este miembro en este caso llamado Ashley. Luego esperamos a que aparezca esta página y presionamos el botón de retroceso y esperamos a que nos redirija de vuelta a la página original. Y estoy usando la biblioteca de pruebas en React para esto.
¿Esta prueba fallará cuando algo salga mal? A menos que la API cambie, es decir, a menos que la respuesta del back-end cambie, esta prueba fallará cuando algo importante salga mal en el front-end. Y si tienes muchas de estas respuestas de API que debes simular o falsificar, recomiendo usar algo como Netflix PolyJS, que puede reproducir las solicitudes HTTP por ti y almacenarlas automáticamente, para que siempre estés sincronizado con tu back-end, lo cual es genial. ¿La prueba solo fallará cuando algo salga mal? Nuevamente, depende un poco. Si tu copia cambia, si dependes de roles, etiquetas ARIA, tal vez incluso identificadores de prueba, cosas así. Entonces, si alguno de esos cambia, tu prueba también fallará. Sin embargo, para mí, ese es un cambio que afecta a los usuarios. Así que estoy feliz de actualizar mis pruebas en esos casos.
Genial. Veamos una tecnología diferente que se puede utilizar para el mismo tipo de prueba. En este caso, usamos Cypress. Cypress sube un nivel más en la pila, por lo que ahora estamos probando directamente en el navegador. Y nuevamente, interceptamos la llamada a nuestro back-end, porque aún no queremos interactuar con eso, y reemplazamos los datos devueltos por esa API con uno falso. Luego visitamos nuestra aplicación web real, llamémosla así, y luego afirmamos que estamos en esta página, hacemos clic en el miembro, nos aseguramos de que aterricemos en la siguiente página, presionamos el botón de retroceso, y queremos volver a la otra página. Y al igual que antes, esta prueba tiene las mismas ventajas y desventajas que la anterior.
5. Debugging with Cypress and End-to-End Testing
Cypress viene con una herramienta de depuración visual que te permite observar la ejecución de la prueba y observar cada paso. Arreglamos tres errores, pero las renovaciones de descuentos para estudiantes estaban cayendo debido a un fallo en la compilación. Nuestras pruebas de extremo a extremo ayudaron a depurar el problema al parecerse mucho a las pruebas manuales. Al crear un usuario real y navegar por el sitio web real, podemos convertir una prueba de integración en una prueba de extremo a extremo.
Entonces, si cambias el texto, es posible que también tengas que cambiar tus pruebas, etc. Sin embargo, una cosa que Cypress hace excepcionalmente bien es que viene con una herramienta de depuración visual que se ve algo así. En ella, puedes observar la ejecución de la prueba y pasar el cursor sobre cada paso para observar exactamente lo que está sucediendo. Esto es realmente muy útil para depurar tus pruebas. Veamos cómo se ve eso.
Genial. Bien. Ya hemos solucionado tres errores, nos hemos asegurado de que nunca puedan volver porque tenemos pruebas para ellos. Pero ese día, la persona de mi equipo que estaba de guardia recibió una alerta porque las renovaciones de descuentos para estudiantes estaban cayendo en picada. Resulta que gran parte de Spotify.com depende de PHP y Bootstrap. Esa es la parte heredada de nuestro sitio web. Cuando lanzamos en India hace aproximadamente un año, agregamos una nueva bandera, la bandera de India, a nuestra distribución de paquetes de Bootstrap. Desafortunadamente, la compilación falló, pero de alguna manera aún se implementó en producción. Y eso tuvo el efecto de que todo el JavaScript relacionado con Bootstrap, en este caso, por ejemplo, nuestros modales, comenzaron a fallar.
Entonces, esto es lo que generalmente se ve en el flujo. Presionamos siguiente aquí y deberíamos ver este modal. Y al continuar, vamos a nuestro socio de verificación de estudiantes, shoreID. Sin embargo, ese día, en lugar de eso, los usuarios experimentaban algo como esto durante aproximadamente dos horas. No sucede nada. Bien. Desafortunadamente, nuestras pruebas no detectaron esto. En cambio, nuestras pruebas ayudaron a depurar este problema. Y en particular, fueron nuestras pruebas de extremo a extremo las que nos ayudaron en este caso.
Entonces, ¿qué es una prueba de extremo a extremo? Son las pruebas que se asemejan más a las pruebas manuales. Estás en el entorno de producción o en un entorno que se asemeja mucho a la producción y haces clic de forma programática como lo haría un usuario. Y eso suena mucho como nuestras pruebas anteriores, ¿verdad? Nuestra prueba de integración con Cypress. Resulta que simplemente creando un usuario real, iniciando sesión con ese usuario y navegando por el sitio web real en lugar del local, básicamente convertimos una prueba de integración en una prueba de extremo a extremo. En este caso, para canjear descuentos para estudiantes, la prueba se vería algo así. Primero creamos un usuario estudiante, iniciamos sesión con ese usuario y lo configuramos en el último año de su descuento para estudiantes. Luego visitamos el entorno de pruebas.
6. Functional and Visual Testing
Estas funciones se comparten entre equipos para el uso de todos. Nos aseguramos de que el flujo de aterrizaje en la página de inicio, hacer clic en los CTAs, ir a la siguiente página y verificar si llegamos a la página correcta. Estas pruebas pueden ser un poco inestables y tardar más en ejecutarse, por lo que las ejecutamos después de implementar en producción. Los errores visuales, especialmente en las páginas heredadas, pueden ser difíciles de encontrar. Las pruebas de instantáneas ayudan a prevenir estos problemas al renderizar componentes en archivos y verificar los cambios. Las pruebas de instantáneas fallan ante cualquier cambio.
Estas funciones, por cierto, se comparten entre diferentes equipos, para que todos puedan usarlas. Luego nos aseguramos de aterrizar en la página de inicio. Hacemos clic en el primer CTA. Vamos a la siguiente página. Nos aseguramos de que estemos allí. Hacemos clic en Renovar Descuento. Luego verificamos que el nombre de la ruta cambie y aterricemos en la página correcta. Hacemos clic en Siguiente. Nos aseguramos de que se abra el modelo y que, al hacer clic en Continuar, aterricemos en Share I.D., nuestro socio de verificación.
Genial. Entonces, ¿esta prueba fallará cuando algo salga mal? Sí, absolutamente. Lo hará. Y estas son especialmente útiles para las partes en las que muchos equipos contribuyen al mismo código base o a los mismos flujos, porque hay tantas interacciones diferentes que pueden salir mal. Sin embargo, esa también es la parte débil de estas pruebas. ¿Solo fallarán cuando haya algo mal? No, porque hay tantas cosas diferentes que podrían ser inestables, estas pruebas también pueden ser un poco inestables. Además, suelen tardar un poco más en ejecutarse, por lo que no las ejecutamos como parte de nuestra canalización de integración continua, sino después de implementar en producción. Aunque son una herramienta extremadamente útil para depurar lo que está sucediendo o lo que está mal y para verificar que todo siga funcionando correctamente, personalmente no las ejecutamos como parte de nuestra canalización de integración continua.
De acuerdo. Ahora hemos hablado mucho sobre diferentes tipos de errores funcionales, tal vez estés pensando, ¿qué hay de los errores visuales? Y los errores visuales para mí durante mucho tiempo fueron los más difíciles de encontrar, especialmente en la parte heredada de nuestro sitio web donde usamos Bootstrap en todas partes, un simple cambio en CSS podría tener consecuencias fatales, como aquí donde cambiamos una línea de CSS y de repente el proceso de pago se ve completamente roto. Pero no solo en las páginas heredadas tenemos estos problemas. Este botón, por ejemplo, me persigue absolutamente. Se ha caído debajo de esta barra de navegación no sé cuántas veces y cada vez que intentamos subirlo de nuevo, tres días después vuelve a estar bajo.
Entonces, ¿cómo prevenimos este tipo de problemas? Una forma es a través de las pruebas de instantáneas. Y una prueba de instantánea es básicamente renderizar un componente en un archivo y luego, en cambios posteriores, asegurarse de que el archivo siga viéndose igual. Estos archivos se ven un poco así, o más bien así. Se vuelven extremadamente, extremadamente largos. Este en particular, creo que tiene mil ochocientas líneas. Y ese es exactamente el problema que veo con estas pruebas. ¿Fallarán cuando algo salga mal? Absolutamente. Pero, ¿solo fallarán entonces? No, fallan ante cualquier cambio.
7. Automated Visual Regression Testing
Las pruebas automatizadas de regresión visual reemplazan las pruebas de instantáneas al comparar capturas de pantalla de los cambios en cada rama para cada historia en Storybook. Esta herramienta proporciona un resumen de los cambios directamente en su solicitud de extracción. Puede construir esto internamente o utilizar herramientas como Persi, Loki, Storyshots, Backstop.js o Cypress con Puppeteer. Estas pruebas no fallan, pero informan cualquier cambio, lo que facilita la comparación de capturas de pantalla en lugar de líneas de CSS. Sin embargo, las animaciones pueden causar inestabilidad, lo que requiere desactivar las animaciones.
Y debido a que fallan con tanta frecuencia y debido a que los cambios son tan grandes que ni siquiera GitHub quiere mostrar la diferencia por defecto, se vuelven un poco propensos a errores. Las personas comienzan a ignorarlos en lugar de confiar realmente en ellos. Y lo único peor que no tener pruebas son las pruebas en las que no puedes confiar pero que aún te dan una falsa sensación de seguridad. Entonces, ¿hay una mejor manera? Creo que sí.
Hay pruebas automatizadas de regresión visual. Así como las pruebas de instantáneas, ahora tomamos capturas de pantalla en lugar de capturar el resultado en HTML y CSS. Y lo que hacemos en Spotify es hacer esto en cada rama para cada historia en Storybook, y luego comparar esas capturas de pantalla con las que tenemos en la rama principal. Esta es la herramienta que hemos construido internamente. Este es uno de los modos en los que puedes verlo. Como puedes ver aquí, obtienes un resumen de todas las cosas que han cambiado directamente en tu solicitud de extracción, lo cual es extremadamente útil. Puedes construir esto internamente, o puedes usar una herramienta como Persi o Loki o Storyshots si usas Storybook, o puedes escribir la tuya propia utilizando algo como Backstop.js o Cypress con Puppeteer.
Y nuevamente, ¿estas pruebas fallarán cuando algo salga mal? En realidad, no fallan, simplemente informan que algo ha sucedido, que algo ha cambiado. Pero sí, ¿solo harán eso entonces? No, al igual que las pruebas de instantáneas anteriores, fallarán ante cualquier cambio. Sin embargo, al menos para mí, es mucho más fácil ver 20 capturas de pantalla y compararlas que ver 200 o tal vez 1,000 líneas de CSS que han cambiado. Y una advertencia con estas pruebas es que a veces, si tienes muchas animaciones, puede volverse un poco inestable, por lo que hemos tenido que desactivar las animaciones.
Conclusion and Q&A
Probar los frontends ya no es tan intimidante como solía ser. Hay muchas herramientas bien documentadas disponibles y debemos tener confianza en nuestras aplicaciones para nuestros usuarios. Gracias por estar aquí y vamos a responder las preguntas.
Muy bien. Esos fueron todos los errores que he preparado para ustedes hoy. ¿De dónde seguimos ahora? En primer lugar, espero haberles mostrado que testing los frontends ya no es una tarea tan intimidante como solía ser. Hay un montón de herramientas disponibles. Espero haberles mostrado algunas de ellas rápidamente. Todas están muy bien documentadas, y realmente no hay excusa para no usarlas. Si aún no saben por dónde empezar, tomen las dos preguntas que les presenté y enfoquense en encontrar una solución que maximice la relación esfuerzo-confianza. Porque al final del día, de eso se trata testing, darte la confianza de que tu aplicación funciona. Y si me preguntan, le debemos esa confianza a nuestros usuarios.
Gracias. Muchas gracias por estar aquí. Gracias por recibirme. Por supuesto. De hecho, tengo un par de amigos ex-colegas que se unieron a Spotify recientemente, así que vean si pueden encontrarlos. Un saludo a Simon, Aaron y Artie. Pero gracias por su charla. Vamos directo a las preguntas porque tenemos muchas.
Enfoque de Desarrollo Dirigido por Pruebas
Personalmente, no suelo utilizar TDD, a menos que esté corrigiendo errores. Si veo que algo está mal, primero escribo una prueba para asegurarme de capturar el error y luego lo corrijo. Si desarrollo una nueva funcionalidad, depende de si veo algo que pueda ser complicado. En ese caso, puedo escribir la prueba primero, pero no siempre lo hago.
Muy bien, la primera pregunta es, ¿utilizas estas técnicas como parte del desarrollo dirigido por pruebas o creas estas pruebas después de haber desarrollado tus funciones? Personalmente, no suelo utilizar TDD, a menos que esté corrigiendo errores. Así que si veo que algo está mal, primero escribo una prueba para asegurarme de capturar el error y luego lo corrijo. Así que veo la luz pasar de rojo a verde. Si desarrollo una nueva funcionalidad, depende de si veo algo como, bueno, esto podría ser complicado. En ese caso, puedo escribir la prueba primero, pero no siempre lo hago. Y no hay una regla que diga que debes hacerlo así en Spotify. Hasta donde yo sé.
Proceso de Pruebas y Manejo de Errores
Existen preguntas sobre la ejecución de pruebas al confirmar o enviar cambios, el tiempo que lleva ejecutar las pruebas y los planes para abrir el código de la herramienta de regresión visual. La ejecución de pruebas como parte del flujo de trabajo toma menos de 15 minutos para mil pruebas. También se ejecutan pruebas durante el desarrollo, no solo al confirmar cambios. La decisión de abrir el código de la herramienta de regresión visual aún está siendo considerada. Se han detectado errores mediante pruebas, pero algunos aún han llegado a producción.
Sí, eso es un buen trabajo. Hablando de ti en Spotify, hay un par de preguntas sobre tu proceso con una escala tan grande como la tuya. Esto es un poco como una pregunta de dos partes, una es, ¿ejecutas pruebas al confirmar o enviar cambios? Y si es así, ¿cuáles, y dos, ¿se tarda mucho tiempo en ejecutar todas estas pruebas? ¿Y hay alguna forma de mejorar eso? ¿Verdad? ¿Verdad?
Si piensas en, ya sabes, microservicios en el backend, también estamos tratando de mantener nuestro frontend relativamente pequeño. Así que mi equipo se encarga de esta parte del sitio web y tenemos alrededor de, creo que mil pruebas que cubren eso. Y se ejecutan tal vez en el flujo de trabajo, tarda menos de 15 minutos. No es el más rápido, pero ya sabes, generalmente está bien esperar 15 minutos al menos en, en nuestro equipo antes de poder fusionar. Así que las ejecutamos como parte de nuestros flujos de trabajo y no puedes fusionar si las pruebas no están en verde, por supuesto.
Eso está bastante bien. Y luego, ¿ejecutas alguna al confirmar versus enviar cambios? Quiero decir, mientras estoy desarrollando, si estoy escribiendo pruebas, que es lo que hago mientras desarrollo, también ejecuto al menos una prueba unitaria. Como si estuviera escribiendo pruebas unitarias, dejo que las pruebas unitarias se ejecuten en modo de observación mientras escribo las pruebas. Si escribo pruebas de Cypress, tengo mi ventana de Cypress abierta junto a mi editor. Así que sí, no es al confirmar. Es durante el desarrollo. Y luego también en el flujo de trabajo al enviar cambios.
Seguridad primero, ¿verdad? Tenemos una pregunta. ¿Tienen planes de abrir el código de la herramienta de regresión visual que mostraste en tu charla? Eso es interesante. Creo que lo han considerado. No es mi equipo el que lo escribió, pero ahora estamos considerando cambiar a una herramienta de pago. Así que no creo que vayamos a abrir el código de esta por ahora. Incluso podríamos dejar de usarla. Exactamente. Es muy útil, sin embargo. Eso es genial. Porque nos has mostrado algunos errores que tus pruebas detectaron, lo cual, quiero decir, creo que es la mayor prueba de que las pruebas son realmente importantes. Pero, ¿alguno de tus errores ha llegado a producción? Estoy seguro de que todavía están ahí, incluso algunos de ellos. Uno que se me ocurre es, por ejemplo, la parte del sitio web en la que trabajamos, incluimos nuestro SBA dentro de una aplicación más grande, la plataforma de cuentas, y debido a eso, si, digamos, estilizas algo con una altura del 100%, eso puede no ser lo mismo en tu SBA y en tu storybook como en el sitio web en vivo. Y debido a que algunas de nuestras pruebas, o la mayoría de nuestras pruebas, se ejecutan solo directamente en el SBA, una vez empujé accidentalmente algo que hizo que todo el sitio web se escalara de una manera realmente extraña. Afortunadamente, porque sabía que era un riesgo, y porque ejecutamos nuestras pruebas de regresión visual solo en el SBA, lo verifiqué justo después de implementarlo y lo retiré directamente después. Así que aún así, se detectó rápidamente, pero sí, mis errores podrían llegar a producción como los de cualquier otra persona.
Manejo de Errores y Pruebas de Regresión Visual
He tenido muchos errores en el pasado, pero no entraré en detalles. Revisamos el código de los demás, por lo que si ocurre un error, es nuestra responsabilidad colectiva. En cuanto a simular APIs en pruebas de integración, utilizamos PolyJS para reducir el riesgo de cambios en la API. No escribimos pruebas para la compatibilidad con versiones anteriores porque la gestión de versiones se encarga de eso. Las pruebas de regresión visual se pueden realizar sin Storybook utilizando herramientas como Persi, Loki y Backstop.js. Para evitar repetir pruebas, extraemos el código común en funciones de utilidad.
Sí, he tenido muchos, pero no voy a hablar de ellos, porque es algo del pasado. Es algo del pasado. Al mismo tiempo, ¿verdad?, no hay culpa tampoco, porque como no, sí. Reviso el código de todos los demás, y todos los demás revisan mi código, y si algo entra y causa un error, es culpa de todos nosotros, no solo de quien escribió el código, así que.
Sí, seguro. Ya tenemos un par de preguntas más de la audiencia. Entonces Lee pregunta, ¿siempre simulas APIs al ejecutar pruebas de integración y solo llamas a la API real en pruebas de extremo a extremo fuera de tu flujo de CI? Para mi equipo, eso es cierto, sí. Pero en este caso, para simular usamos una herramienta llamada PolyJS, que básicamente llama a tus APIs reales y luego almacena la respuesta en tu extremo. Así se reduce el riesgo de que la API cambie mientras el front-end no lo hace mientras desarrollas. No es realmente una garantía después de implementar, pero al menos mientras desarrollas, notarías esas diferencias.
¿Sueles escribir pruebas para comprobar la compatibilidad con versiones anteriores de tu front-end con el back-end? No, porque la gestión de versiones de las APIs se encarga de eso, generalmente. Hasta ahora no hemos tenido problemas con eso.
Genial. Floros pregunta, ¿puedes implementar pruebas de regresión visual sin tener los componentes en Storybook? Absolutamente. De hecho, al principio no teníamos realmente Storybook. Simplemente construimos nuestra propia página donde demostramos los componentes, que es lo que hace Storybook. Era mucho menos bonito. No tenía una API ni nada, pero funciona, e incluso si solo le das URLs en vivo si no tienes un inicio de sesión o algo así, siempre que tengas una herramienta que pueda tomar capturas de pantalla y le des algunas URLs, puedes hacer pruebas de regresión visual.
Eso es genial. Creo que hay algunas herramientas que recomendaste en tu charla, ¿verdad? Sí. Persi, creo que lo hace. Loki, StoryShots, creo que es otra. O Backstop.js es una herramienta que puedes usar para comparar las capturas de pantalla, y luego puedes usar Puppeteer o Cypress o cualquier framework de pruebas de extremo a extremo para tomar capturas de pantalla de tu sitio web. Genial. Gaddi pregunta, ¿cómo te aseguras de no repetir las mismas pruebas con pruebas unitarias, de integración, de extremo a extremo, etc.? Huh. ¿Y te ha pasado alguna vez? No lo creo. Tal vez? Nunca me ha pasado, al menos no ha sido un problema. A veces, copiamos y pegamos un poco, pero incluso ahí, como las pruebas también son código, intentamos mantenerlo seco al menos un poco. Para no encontrarnos con ese problema, intentaríamos extraer algunas de las pruebas en alguna función de utilidad o algo así, y luego tu prueba vuelve a ser legible. Evitas, ya sabes, copiar el mismo código varias veces.
Starting Testing and Test Coverage
Si nunca has hecho pruebas antes, te recomiendo comenzar con pruebas de extremo a extremo. Demuestra que puedes escribir una prueba para tu flujo más importante en 10-15 minutos. Otro consejo es escribir una prueba para cada error que encuentres. La cobertura de pruebas no es una métrica excelente, pero la utilizamos para encontrar áreas que necesitan una mejor prueba.
Y quiero decir, en el peor de los casos, solo tienes más pruebas, más respaldos. Exactamente. Se ejecuta un poco más lento, pero mejor duplicar que hacer un largo recorrido. Sí, exactamente.
Tenemos otra pregunta aquí. ¿Dónde recomendarías comenzar si nunca has hecho testing antes? ¿Alguna vez has considerado crear un curso, porque les encantó cómo explicaste todo? Eso es muy amable. Gracias. Creo que dos cosas. Una forma de comenzar testing, creo, es a través de pruebas de extremo a extremo. Si solo quieres asegurarte o obtener la aprobación de alguien. Solo muestra que puedes escribir una prueba de extremo a extremo para tu flujo más importante en 10-15 minutos en Cypress u otra herramienta. Y luego no tienes que probarlo manualmente cada vez que lo implementes, lo cual es enorme. La otra cosa que recomendaría es que si decides comenzar testing cada error que tengas, escribe primero una prueba para ello. Así sabes que nunca volverá. Ese es un gran consejo. Sí. Esas serían las dos cosas con las que comenzaría.
Tengo una última pregunta rápida, porque se nos está acabando el tiempo. ¿Cuál es tu perspectiva sobre la cobertura de pruebas y si tienes alguna métrica de prueba que uses? Sí, observamos la cobertura de pruebas, pero principalmente desde la perspectiva de qué no estamos probando. No creo que la cobertura de pruebas sea una métrica excelente para mostrar, ya sabes, OK, ahora tengo un 90 por ciento y ya no tengo que probar más. Eso no es muy útil. No tenemos un número exacto de cuál es nuestro objetivo o nuestra meta. Sería diferente, creo, si estuviéramos desarrollando, digamos, una herramienta para otra persona en lugar de un sitio web para el usuario final. Pero sí, lo que hacemos con la cobertura es definitivamente encontrar áreas o cosas que no probamos lo suficientemente bien. Eso es genial. Bueno, muchas gracias, Iris, por unirte a nosotros. Y creo que Iris estará en una sala de Zoom después de esto, si aún tienes más preguntas. Que tengas una buena noche. ♪♪♪ ♪♪♪
Comments