Pruebas automatizadas de regresión de rendimiento con Reassure

Rate this content
Bookmark

Como desarrolladores, nos encanta sumergirnos en métricas de rendimiento, comparar soluciones y realizar pruebas de rendimiento. Aunque no siempre nos guste, a menudo nos vemos obligados a solucionar problemas de rendimiento en nuestras aplicaciones de React y React Native. Pero este proceso no es sostenible y propenso a regresiones, especialmente a medida que la aplicación y el equipo crecen. Lo peor de todo es que estos problemas a menudo son descubiertos por los usuarios, lo que hace que su experiencia sea miserable. En mi charla te presentaré Reassure, una biblioteca de pruebas de regresión de rendimiento para React y React Native, que resulta ser una pieza faltante en nuestras suites de pruebas automatizadas y rendimiento. Detectando problemas antes de que lleguen a producción.

16 min
24 Oct, 2022

Video Summary and Transcription

La charla de hoy presenta Reacher, una herramienta de monitoreo de rendimiento para bases de código de React y React Native. Destaca la necesidad de detectar regresiones de rendimiento temprano en el proceso de desarrollo e identifica el mal uso de JavaScript como una fuente común de problemas de rendimiento. ReaSure, desarrollado por Covstack, se presenta como una biblioteca prometedora que se integra con los ecosistemas existentes y proporciona mediciones confiables de tiempo de renderizado y conocimientos útiles para la revisión de código. Se discuten consideraciones para operar en un VM de JavaScript, incluyendo JIT, recolección de basura y caché de resolución de módulos. Se menciona el análisis estadístico utilizando el z-score como un método para determinar la importancia de los resultados de las mediciones.

Available in English

1. Introduction to Performance Monitoring

Short description:

Hoy voy a hablar sobre el monitoreo del rendimiento en los codebases de React y React Native con Reacher. La entropía es el aumento del desorden, que distingue el pasado del futuro. Como desarrolladores, luchamos contra la entropía siguiendo un ciclo de desarrollo y solucionando errores. Sin embargo, incluso con un flujo de trabajo bien diseñado, pueden aparecer críticas negativas.

Hola, hoy voy a hablar sobre el monitoreo del rendimiento y cómo hacerlo en tus codebases de React y React Native con Reacher. Me llamo Michał Pieszchala, soy el Jefe de Tecnología en Callstack, responsable de nuestra investigación y desarrollo y esfuerzos de código abierto. También soy un colaborador principal en una serie de bibliotecas, actualmente manteniendo el React Native CLI y la biblioteca de pruebas de React Native.

Comencemos con algo de inspiración, ¿de acuerdo? ¿Alguien ha oído hablar de la entropía? No realmente esta. La entropía del mundo real, descrita por la física de esta manera. O cómo lo enmarcó Stephen Hawking. Puedes ver una taza de té caerse de una mesa y romperse en pedazos en el suelo, pero nunca verás que la taza se reúna y salte de nuevo a la mesa. El aumento del desorden, o esta entropía, es lo que distingue el pasado del futuro, dándole una dirección al tiempo. O en otras palabras, las cosas eventualmente se desmoronarán si no se les presta atención.

Pero no nos pongamos demasiado deprimidos o cómodos con las cosas que se convierten en caos, porque podemos y debemos luchar contra ello. Podemos hacer esfuerzos para crear tipos útiles de energía y orden, lo suficientemente resistentes como para resistir la implacable atracción de la entropía al gastar esta energía. Cuando desarrollamos software, sentimos que la entropía es algo real. Es por eso que generalmente hacemos un esfuerzo adicional y seguimos algún tipo de ciclo de desarrollo. Por ejemplo, comenzamos agregando una nueva función. Durante el desarrollo, la acompañamos con una serie de pruebas. Cuando terminamos, la enviamos a QA. QA la mejora y promueve nuestro código para su lanzamiento en el canal de producción. Y volvemos a agregar otra función. Pero eso es una versión bastante simplificada de lo que generalmente hacemos. Complicémoslo un poco. Entre otras cosas, no tenemos en cuenta que los errores pueden aparecer repentinamente. Ahora nuestro círculo se convierte en un grafo, pero está bien porque sabemos qué hacer. Necesitamos identificar la causa raíz, agregar una prueba de regresión para que nunca vuelva a romperse, enviarla a QA una vez más, enviarla y volver a agregar nuevas funciones.

Entonces estamos contentos con nuestro flujo de trabajo. Funciona bastante bien. Agregamos función tras función, nuestra versión de la aplicación está tan bien diseñada que incluso agregar 10 nuevos desarrolladores no nos ralentiza. Y luego echamos un vistazo a las reseñas de nuestra aplicación para ver qué piensan las personas. Y aparece una reseña salvaje de una estrella. Y luego llega otra más.

2. Challenges with Performance Monitoring

Short description:

Nuestro flujo de trabajo perfecto no es resistente a las regresiones de rendimiento. Necesitamos una forma de detectarlas antes de que afecten a nuestros usuarios. Tratar los problemas de rendimiento como errores nos permite detectar las regresiones temprano en el proceso de desarrollo. Para encontrar la mejor herramienta para las pruebas de rendimiento, debemos considerar el impacto y enfocarnos en las regresiones más probables. La mayoría de los problemas de rendimiento se originan en el lado de JavaScript, particularmente por un mal uso de React. Estimamos que alrededor del 80% del tiempo dedicado a solucionar problemas de rendimiento se encuentra en el ámbito de JavaScript. Encontramos una prometedora biblioteca de pruebas de rendimiento para React que vale la pena explorar.

Y simplemente... siguen llegando. Y empezamos a darnos cuenta de que nuestro flujo de trabajo perfecto basado en la ciencia, nuestras experiencias y las mejores prácticas, que se suponía que evitaría que nuestra aplicación se desmoronara, no es resistente a un tipo particular de errores. Regresiones de rendimiento. Nuestro código no tiene las herramientas para combatir esto. Sabemos cómo solucionar los problemas una vez que los detectamos, pero no tenemos forma de detectarlos antes de que afecten a nuestros usuarios.

Entonces, ¿cómo era de nuevo? O... El rendimiento se desmoronará eventualmente cuando no se haya previsto. Así que si no hago nada para optimizar mi aplicación mientras agrego nuevo código y dejo que el tiempo pase, se volverá más lenta. Y no sabemos cuándo sucederá. Tal vez mañana, tal vez en una semana, o en un año. Y si solo hubiera una forma establecida de detectar al menos algunas de las regresiones temprano en el proceso de desarrollo, antes de que nuestros usuarios se den cuenta. ¡Espera un minuto, la hay! Si comenzamos a tratar los problemas de rendimiento como errores, ni siquiera necesitamos interrumpir nuestro flujo de trabajo de desarrollo. Las pruebas de regresión se ejecutan en un entorno remoto, en cada cambio de código, así que solo necesitamos encontrar una forma de incluir las pruebas de rendimiento allí, ¿verdad?

Pero antes de salir a buscar la mejor herramienta, demos un paso atrás y pensemos en el impacto y en lo que vale la pena probar. Al igual que con cualquier cobertura de pruebas, hay una proporción saludable a la que aspiramos, para proporcionarnos el mejor valor con el menor esfuerzo. Queremos asegurarnos de enfocarnos en las regresiones que es más probable que afecten a nuestros usuarios. Y al parecer, estamos desarrollando una aplicación reactivada. Por cierto, ¿sabías que hay una fuente llamada Impact? Y probablemente la hayas visto en memes. De todos modos, echemos un vistazo a los problemas típicos de rendimiento con los que los desarrolladores se enfrentan a diario. Listas e imágenes lentas, SVG, mal uso del contexto de React, re-renderizaciones, TCI lento, solo por mencionar algunos. Si observamos esta lista desde el punto de vista del origen del problema, notaremos que la gran mayoría de ellos provienen del lado de JavaScript. Ahora, veamos la frecuencia relativa. Y lo que emerge es bastante revelador. Estimamos que la mayor parte del tiempo que nuestros desarrolladores dedican a solucionar problemas de rendimiento, alrededor del 80%, proviene del ámbito de JavaScript, especialmente por un mal uso de React. Solo el resto es la sobrecarga de comunicación entre puentes y el código nativo, como la renderización de imágenes o las operaciones de la base de datos que funcionan de manera ineficiente. Pero no soy partidario de reinventar la rueda, así que he buscado en Google una biblioteca de pruebas de rendimiento para React, y encontré esto. Este paquete. Parece prometedor. Veamos qué hay dentro. No es muy popular, pero está bien. La última versión se lanzó hace 9 meses.

3. Introduction to ReaSure

Short description:

Necesitamos una nueva biblioteca que se integre con nuestro ecosistema existente, mida los tiempos de renderizado de manera confiable, proporcione un ejecutor de CI, genere informes legibles y analizables, y ofrezca información útil para la revisión de código. Les presento ReaSure, un compañero de pruebas de regresión de rendimiento para aplicaciones de React y React Native. Desarrollado por Covstack en colaboración con Intane, ReaSure mejora el proceso de revisión de código al integrarse con GitHub. Ejecuta Jest a través de código Node con parches especiales para aumentar la estabilidad y utiliza el perfilador de React para manejar las mediciones de manera confiable. ReaSure compara los resultados de las pruebas entre ramas y proporciona un resumen de los resultados categorizados estadísticamente. Abrazar la estabilidad y evitar la inestabilidad es clave para los puntos de referencia cognitivos, especialmente en Node.js.

Está bien. ¿Qué más? Parchea React. Eso no está bien. También utiliza internamente React. Eso es decepcionante. No se ajusta a nuestro caso de uso y no parece una base sólida para construir.

Pero, ¿qué necesitamos realmente de una biblioteca como esta? Idealmente, debería integrarse con el ecosistema existente de bibliotecas que estamos utilizando. Debería medir los tiempos de renderizado y contar de manera confiable, tener un ejecutor de CI, generar informes legibles y analizables, proporcionar información útil para la revisión de código y, según nuestra biblioteca de Google, tener un diseño estable. Y dado que no hay nada como esto disponible, necesitamos una nueva biblioteca.

Y me gustaría presentarles ReaSure, un compañero de pruebas de regresión de rendimiento para aplicaciones de React y React Native. Se desarrolla en Covstack en colaboración con Intane, uno de los grupos de apuestas y juegos más grandes del mundo. ReaSure se basa en su configuración existente y la complementa con una API de medición de rendimiento discreta. Está diseñado para ejecutarse en un entorno de servidor remoto como parte de su integración continua. Para aumentar la estabilidad de los resultados y reducir la inestabilidad, ReaSure ejecutará sus pruebas una vez para la rama actual y otra vez para la rama base. Una experiencia de desarrollo agradable es fundamental en nuestro diseño de ingeniería. Es por eso que ReaSure se integra con GitHub para mejorar el proceso de revisión de código. Actualmente, aprovechamos Danger.js como nuestro backend de bot, pero en el futuro nos gustaría preparar una acción de GitHub plug-and-play.

Ahora, veamos qué hace. ReaSure ejecuta Jest a través de código Node con parches especiales para aumentar la estabilidad. La función measureRender que proporcionamos utiliza el perfilador de React para manejar las mediciones de manera confiable, lo que nos permite evitar el parcheo de React. Después de completar la primera ejecución, cambiamos a la rama base y ejecutamos las pruebas nuevamente. Una vez que se completan ambas ejecuciones de pruebas, la herramienta compara los resultados y presenta el resumen, mostrando resultados categorizados estadísticamente en los que se puede actuar. Volvamos a nuestro ejemplo. Observa cómo creamos un nuevo archivo con la extensión .perf-test-.dsx, que reutiliza nuestra prueba de componente regular de la biblioteca React en una función de escenario. Luego, el método measurePerformance de ReaSure utiliza el escenario para renderizar nuestro componente contador, en este caso, 20 veces. Bajo el capó, el perfilador de React mide los tiempos de renderizado y la cantidad de veces que se renderiza, que luego escribimos en el sistema de archivos. Y eso es generalmente todo lo que tienes que escribir. Copia y pega tus pruebas existentes, ajústalas y disfruta. Los puntos de referencia cognitivos no son pan comido, incluso en entornos que no son de JS. Pero es particularmente complicado con Node.js. La clave es abrazar la estabilidad y evitar la inestabilidad.

4. Consideraciones para JavaScript VM

Short description:

Al operar en un JavaScript VM, debemos tener en cuenta el JIT, la recolección de basura y el almacenamiento en caché de resolución de módulos. El análisis estadístico requiere ejecutar las mediciones varias veces. El z-score se utiliza para determinar la significancia estadística de los resultados.

Al operar en un JavaScript VM, debemos tener en cuenta el JIT, la recolección de basura y el almacenamiento en caché de resolución de módulos. Tenemos un costo de concurrencia que nuestro ejecutor de pruebas asume para una ejecución rápida. Necesitamos decidir qué promediar y qué percentil tomar. Y mucho más. Por ejemplo, para realizar un análisis estadístico. Para asegurarnos de que nuestros resultados de medición tengan sentido matemáticamente, no es suficiente ejecutarlos una o dos veces. Teniendo en cuenta otras cosas, hemos determinado que diez veces es una buena referencia. Luego, para determinar la probabilidad de que el resultado sea estadísticamente significativo, necesitamos calcular el z-score, que requiere el valor medio o la divergencia promedio y la desviación estándar. Esto me trae recuerdos de la universidad, así que no voy a profundizar aquí. Ahora, el almacenamiento en caché de resolución de módulos es algo que es genial para las aplicaciones de Node.js, pero nos causó problemas al desarrollar la biblioteca. Resultó que la ejecución posterior del mismo componente a menudo resultaba en ejecuciones incluso diez veces más lentas. Como puedes imaginar, promediar eso haría que los resultados no fueran confiables. Por lo tanto, descartamos la prueba más lenta, ya que probablemente está limitada por la falta de caché. Con todos esos datos, podemos presentar los tiempos de duración de renderizado como estadísticamente significativos o sin sentido. Además de los tiempos de renderizado, otra métrica útil que puede degradarse fácilmente son los recuentos de renderizado, que obtenemos de forma gratuita del Profiler de React. Toda esta información se almacena en formato JSON para su análisis posterior y en Markdown para su legibilidad. Utilizamos la salida de Markdown como fuente para el bot de comentarios de GitHub, impulsado por Danger.js. Esta es, con mucho, nuestra forma favorita y recomendada de usar ReaSure, ya que enriquece el proceso de revisión de código y nos permite mitigar la inestabilidad de la CI que estamos utilizando. Permíteme compartir lo que hemos aprendido hasta ahora al usar esta biblioteca. Debes cubrir los escenarios de usuario más importantes. Incluso si no tienes problemas de rendimiento ahora, los detectarás si aparecen. Prueba pantallas completas o incluso secuencias de pantallas. Las pruebas a nivel de componente son posibles, pero a menudo requieren más ejecuciones de pruebas. Puedes reutilizar tus pruebas de bibliotecas de React Native y Testing si las tienes, y se aplican todas las prácticas establecidas de la biblioteca de pruebas. Haz que tus pruebas se parezcan al comportamiento del usuario y evita simular cualquier cosa que no sea IOH. Debido a sus características, parece que las pruebas de rendimiento frontend se asemejan a las pruebas de extremo a extremo para nuestras aplicaciones. Tiene sentido tratarlas como tal en lugar de en nuestras Trophies o Pirámides de Testing. Recuerda que el rendimiento no es un objetivo, es un camino. Recórrelo con confianza. Hacia EARNED, ReaSure no existiría si no fuera por mis colegas Maciej Jastrzębski, quien es el cerebro detrás de la biblioteca, y un increíble equipo de desarrollo formado por Tomasz y Jakub. Asegúrate de seguir su trabajo. ReaSure es de código abierto. El código QR te redirigirá al repositorio. Dale una estrella si te gusta y avísame si tienes algún problema al adoptarlo. Estaré encantado de ayudarte. Y eso es todo, amigos. Puedes encontrarme en Twitter o GitHub con este nombre de usuario. Que tengas una gran conferencia y gracias.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Top Content
Too much JavaScript is getting you down? New frameworks promising no JavaScript look interesting, but you have an existing React application to maintain. What if Qwik React is your answer for faster applications startup and better user experience? Qwik React allows you to easily turn your React application into a collection of islands, which can be SSRed and delayed hydrated, and in some instances, hydration skipped altogether. And all of this in an incremental way without a rewrite.
TestJS Summit 2021TestJS Summit 2021
33 min
Network Requests with Cypress
Top Content
Whether you're testing your UI or API, Cypress gives you all the tools needed to work with and manage network requests. This intermediate-level task demonstrates how to use the cy.request and cy.intercept commands to execute, spy on, and stub network requests while testing your application in the browser. Learn how the commands work as well as use cases for each, including best practices for testing and mocking your network requests.
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Top Content
Featured Video
The testing pyramid - the canonical shape of tests that defined what types of tests we need to write to make sure the app works - is ... obsolete. In this presentation, Roman Sandler and Gleb Bahmutov argue what the testing shape works better for today's web applications.
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
TestJS Summit 2022TestJS Summit 2022
146 min
How to Start With Cypress
Featured WorkshopFree
The web has evolved. Finally, testing has also. Cypress is a modern testing tool that answers the testing needs of modern web applications. It has been gaining a lot of traction in the last couple of years, gaining worldwide popularity. If you have been waiting to learn Cypress, wait no more! Filip Hric will guide you through the first steps on how to start using Cypress and set up a project on your own. The good news is, learning Cypress is incredibly easy. You'll write your first test in no time, and then you'll discover how to write a full end-to-end test for a modern web application. You'll learn the core concepts like retry-ability. Discover how to work and interact with your application and learn how to combine API and UI tests. Throughout this whole workshop, we will write code and do practical exercises. You will leave with a hands-on experience that you can translate to your own project.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Advanced Conference 2022React Advanced Conference 2022
81 min
Introducing FlashList: Let's build a performant React Native list all together
Top Content
WorkshopFree
In this workshop you’ll learn why we created FlashList at Shopify and how you can use it in your code today. We will show you how to take a list that is not performant in FlatList and make it performant using FlashList with minimum effort. We will use tools like Flipper, our own benchmarking code, and teach you how the FlashList API can cover more complex use cases and still keep a top-notch performance.You will know:- Quick presentation about what FlashList, why we built, etc.- Migrating from FlatList to FlashList- Teaching how to write a performant list- Utilizing the tools provided by FlashList library (mainly the useBenchmark hook)- Using the Flipper plugins (flame graph, our lists profiler, UI & JS FPS profiler, etc.)- Optimizing performance of FlashList by using more advanced props like `getType`- 5-6 sample tasks where we’ll uncover and fix issues together- Q&A with Shopify team