Las condiciones de carrera se encuentran entre algunos de los problemas más desafiantes de detectar y reproducir. Como tal, representan un desafío significativo en el desarrollo, notablemente en la interfaz de usuario. En esta charla, exploramos cómo detectar condiciones de carrera aprovechando las técnicas de fuzzing. Te guiamos a través del descubrimiento del verdadero problema de las condiciones de carrera y cómo impactan en la experiencia del usuario. Te proporcionamos herramientas y ejemplos que demuestran cómo detectarlas fácilmente en tu trabajo diario gracias a las pruebas que se basan en el fuzzing. Después de esta charla, esperamos que tu código React esté libre de condiciones de carrera o al menos que tengas las herramientas adecuadas para ayudarte.
This talk has been presented at React Day Berlin 2023, check out the latest edition of this React Conference.
FAQ
Una condición de carrera, según Wikipedia, es una condición donde el comportamiento sustantivo del sistema depende de la secuencia de tiempo de otros eventos incontrolables.
Nicolas mencionó un ejemplo donde inicialmente buscaba alojamiento en París y luego cambió a buscar en Londres, pero recibió resultados tardíos de París debido a una condición de carrera, lo que resultó en una mala experiencia de usuario.
Nicolas sugiere el uso de pruebas, en particular pruebas automáticas que involucren aleatorización y simulación de llamadas a la API para asegurarse de que el sistema maneje adecuadamente las condiciones de carrera.
Se puede testear un campo de autocompletado en React simulando llamadas a la API y escribiendo en el campo, luego verificando que las sugerencias coincidan con las entradas actuales del usuario, aun cuando las respuestas de la API se entreguen en un orden diferente al solicitado.
FastCheck es un marco de pruebas basado en propiedades que ayuda a probar condiciones de carrera mediante la generación de ejecuciones aleatorias y la gestión de la resolución de llamadas a la API de manera que se pueda verificar la robustez de la aplicación frente a condiciones incontrolables.
Nicolas discute sobre cómo las condiciones de carrera pueden afectar la precisión de los datos financieros en su empresa de planificación de negocios, Pigment, enfatizando la importancia de tener cifras correctas en tiempo real para la toma de decisiones.
Las condiciones de carrera pueden ser complejas de depurar y reproducir, causando frustración para los usuarios. El orador discute ejemplos de condiciones de carrera y formas de solucionarlas y evitarlas. Demuestran un ejemplo de un campo de autocompletado en React y cómo manejar las condiciones de carrera en las llamadas API. El orador introduce el marco FastCheck para pruebas basadas en propiedades para abordar las condiciones de carrera y mejorar las pruebas. La aleatorización de entradas y salidas puede ayudar a descubrir errores específicos para ciertos escenarios. El orador también discute la mitigación de las condiciones de carrera en React y el manejo de la sobrecarga de pruebas y la reproducibilidad.
Hoy, hablaré sobre la condición de carrera. La condición de carrera es compleja de depurar y reproducir. Sucede inesperadamente y puede ser frustrante para los usuarios. Daré ejemplos y discutiré formas de solucionar y evitar las condiciones de carrera. Soy Nicolas, el autor de la biblioteca Fasttech y el fundador de Pigment.
Buenas tardes a todos. Hoy, hablaré sobre la condición de carrera. Mi nombre es Nicolas y la idea es abordar un problema que es complejo de debug, complejo para reproducir, y es por eso que quería discutir la condición de carrera. Porque básicamente, la condición de carrera resulta ser un poco así. Nunca sabes cuándo sucede y probablemente Oh, lo siento. No se suponía que fuera eso. Nunca sabes cuándo sucede y tienes que lidiar con ellos. Pero nos centraremos en la condición de carrera. Aquí hay un ejemplo de condición de carrera. En el pasado, hace unos años, estaba buscando alojamiento en París para ir a París. En el famoso sitio web, no estoy vinculado en absoluto a esta empresa, pero estaba buscando alojamiento en París, y en algún momento, cambié de opinión. Decidí ir a Londres. Puedes ver que estaba buscando alojamiento en Londres. Hay algunos alojamientos bonitos en Londres, y parecen bastante agradables, de hecho. Pero en algún momento, obtuve algunos resultados de París. Esto es exactamente de lo que trata la condición de carrera. Es como algo que pides en algún momento, pero sucede un poco tarde, y recibes resultados más tarde. En algún momento, el usuario se frustra un poco al obtener este resultado. En ese caso específico, es solo una mala UX para el usuario. Ellos lidiarán con eso, y aún podrán usar la aplicación. Pero eso no está bien. Daré algunos ejemplos adicionales para eso. Pero hoy, el objetivo será hablar sobre estas condiciones de carrera y encontrar algunas formas juntos para solucionarlas y evitar que sean una fuente de frustración para los usuarios.
Entonces, como me presenté rápidamente antes, avancemos un poco más. Soy Nicolas. Como se presentó, soy el autor de la biblioteca llamada Fasttech. Puedes tener el enlace allí. Puedes encontrarme en las redes sociales. Pero hablaré un poco sobre mi empresa. Mi empresa es
2. Entendiendo las Condiciones de Carrera
Short description:
Estoy haciendo planificación de negocios y quería hablar sobre las condiciones de carrera. Las condiciones de carrera son importantes para tratar, especialmente en finanzas donde las cifras precisas son cruciales. Una condición de carrera ocurre cuando el comportamiento del sistema depende del tiempo de eventos incontrolables. En una aplicación frontal o React, las entradas de los usuarios y las llamadas a la API son fuentes potenciales de condiciones de carrera. Para ilustrar, volvamos a visitar un video donde busqué estancias en París y cambié de opinión. Las llamadas a la API para París y Londres no devolvieron resultados en el orden esperado, causando una interfaz de usuario defectuosa.
llamado Pigment. Estoy haciendo planificación de negocios. Así que es como para datos financieros, y en finanzas, es importante tener las cifras correctas en el momento correcto en tiempo real. Y esto es principalmente por lo que quería hablar sobre las condiciones de carrera. En el trabajo, no puedo permitirme tener ninguna condición de carrera. Quiero decir, al menos no tener una condición de carrera que haría que las cifras fueran incorrectas, porque la gente las usará para tomar algunas decisiones. Por lo tanto, las condiciones de carrera son muy importantes para tratar, y tienes que ser capaz de lidiar con ellas en algún momento para evitar problemas. Pero veamos juntos qué es una condición de carrera. Y tomaré la definición que viene de Wikipedia. Entonces, una condición de carrera, según Wikipedia, es una condición donde el comportamiento sustantivo del sistema depende de la secuencia de tiempo de otros eventos incontrolables. Lo que me gusta de esta definición es como la secuencia de eventos incontrolables. Y si piensas un poco en tu aplicación frontal o tu aplicación React, porque estamos en una conferencia de React. Tenemos muchos eventos incontrolables. Va desde las entradas de los usuarios. Nunca sabemos cuándo ingresarán cosas en su aplicación a las llamadas a la API. Nunca sabemos cuándo responderá el backend. Y básicamente, estas son fuentes potenciales de condiciones de carrera. Para entender mejor qué es una condición de carrera, volvamos al video que hemos visto juntos cuando estaba buscando estancias en París, y cambié de opinión. Entonces, inicialmente, en este video, he estado buscando estancias en París. Así que hice una llamada para... Y escribí algunas cosas para buscar estancias en París. En este punto, espero que el sitio web estuviera haciendo algún tipo de llamada a la API para obtener estas estancias. En algún momento en el tiempo, debería haber recibido resultado para París, porque era mi consulta inicial. Luego hice una segunda llamada para buscar estancias en Londres. Luego, de nuevo, segunda llamada a la API. Y luego debería haber recibido resultado. En realidad, no sucedió de esa manera. Nunca recibí el resultado para París en el momento correcto. El resultado para París llegó un poco más tarde. Y esa es la razón por la que recibimos una interfaz de usuario defectuosa. Lo hemos visto
3. Ejemplo de Campo de Autocompletado en React
Short description:
Me centraré en un ejemplo muy sencillo de un campo de autocompletado escrito en React. El usuario escribe una consulta y el campo devuelve resultados a medida que escriben. Propondré una implementación ingenua utilizando React y dos estados. El primer estado es la consulta, que se utiliza para llenar una entrada. Cuando el usuario hace cambios en la entrada, se llama a una función llamada actualizar consulta, que establece el estado. Hay un caso especial para la cadena vacía.
algún tipo de interfaz de usuario defectuosa. Porque el resultado para París llegó más tarde. Y en términos de código, el código no piensa en esta posibilidad. Y simplemente se rompe. Para entender mejor cómo funciona y cómo podemos enfrentar o probar la condición de carrera, me centraré en un ejemplo muy sencillo. El ejemplo con esta búsqueda fue interesante. Pero es un poco complejo. Así que tomaré un ejemplo muy sencillo. Consideraremos un campo de autocompletado escrito en React. Campo de autocompletado muy sencillo. Básicamente algo como esto. Tienes un campo. Puedes escribir algunas cosas. Y obtienes algún resultado. Mientras escribes... Así que escribes una letra. Obtienes algún resultado para esta letra. Escribes dos letras. Obtienes resultado para estas dos letras, etcétera. Propondré una implementación muy ingenua para eso. Todo está en React. Está hecho de dos estados. Me centraré en el primero. El primero es una consulta. Así que básicamente el usuario tendrá una consulta. Y esta consulta se utilizará para llenar una entrada. Y cada vez que el usuario haga algunos cambios en la entrada, yo llamaré a una función llamada actualizar consulta. Así que vamos a centrarnos un poco en actualizar consulta. Actualizar consulta comienza estableciendo el estado. Lo cual es bastante normal. Hay un caso especial
4. Manejo de Llamadas API y Pruebas
Short description:
En este caso específico, restablezco las sugerencias a vacío y llamo a la API con la nueva consulta del usuario. Una vez que obtengo el resultado, actualizo el estado de las sugerencias y las renderizo en el componente. Para evitar condiciones de carrera, podemos probar manualmente la entrada o escribir pruebas. Escribí una prueba simple utilizando Jest y la biblioteca de pruebas de React. La prueba simula la API y filtra los resultados en función de la consulta del usuario. Asegura que el resultado será 'banana' y ejecuta el componente.
caso para la cadena vacía. Porque en ese caso específico, no quiero hacer ninguna llamada a la API o algo especial. Así que simplemente restablezco las sugerencias a algo que esté vacío. Y está el caso interesante. Que es como hacer la llamada a la API. Son muy simples. Estoy llamando a la API. Tengo una API que se llama sugerencia cuatro. Estoy llamando a esta API con la nueva consulta que el usuario acaba de escribir. Estoy esperando el resultado. Y tan pronto como obtengo este resultado, lo enviaré a mi estado de sugerencias. Tan pronto como obtenga mi estado actualizado, simplemente renderizaré las sugerencias en el componente. Así que el componente es bastante ingenuo. Es solo un campo con una entrada. Y obtienes la sugerencia a medida que escribes. Así que ahora que tenemos este componente, como estaba hablando de la condición de carrera, la pregunta que podríamos hacernos es ¿cómo nos aseguramos de que no tenemos ninguna condición de carrera? Una de las posibilidades puede ser jugar con la entrada nosotros mismos y comprobar si funciona o no. Pero no es muy fiable. Otra forma sería simplemente escribir pruebas para asegurarnos de que funcionará hoy pero también mañana. Así que vamos a intentarlo. Así que acabo de escribir una prueba en Jest más la biblioteca de pruebas de React. La prueba es bastante simple. Comienza simulando la API. Así que quiero simular la API para sugerencia cuatro. Básicamente, la API solo recibirá una consulta. Y cada vez que reciba una consulta, simplemente filtrará un conjunto de todos los resultados. Es solo una simulación de la API, para no llamar al verdadero backend. También codifiqué la consulta del usuario. No quiero cooperar con todas las consultas del usuario. Solo quiero una de ellas, que es NAN. Y basándome en esta consulta de usuario más en la matriz de posibles resultados que he codificado en la línea tres, puedo saber con seguridad que el resultado será banana y solo banana. Entonces, como yo
5. Ejecutando la Prueba y Manejando Condiciones de Carrera
Short description:
Ejecuto el campo de autocompletado con la API simulada y emulo la escritura del usuario. Me aseguro de que las sugerencias mostradas sean las esperadas y que el número de llamadas a la API coincida con la longitud de la consulta. La prueba pasa, pero la implementación ingenua no maneja las condiciones de carrera. Ilustro el problema con una línea de tiempo donde las llamadas a la API pueden resolverse en desorden.
sé que tengo todas mis entradas listas, ejecutaré el otro componente. Así que básicamente, solo ejecuto el otro componente, que es el campo de autocompletado con la API simulada o sustituida. Y luego emularé a un usuario escribiendo en este campo. Como quiero estar lo más cerca posible de la realidad, simularé a un usuario escribiendo una letra a la vez. Así que solo pongo un pequeño retraso de uno para ver al usuario escribiendo las cosas como lo haría un usuario real. Y ahora que todo está listo, podemos afirmar y podemos ejecutar la prueba. Así que básicamente, quiero estar seguro de que la sugerencia que mostraré a los usuarios es exactamente la que esperaba. Nada más, nada menos. Y que el número de llamadas a la API será exactamente el número de letras en mi consulta. Así que en ese caso, tres. Así que ahora que tenemos todas las pruebas listas, podemos lanzar la prueba. Y esta vez pasa, lo cual es bastante triste, porque básicamente la implementación que sugerí es, diría que es muy simple. Es una ingenua. Y honestamente no he hecho nada para cooperar con la condición de carrera. Así que estaré un poco sorprendido de que funcione de inmediato. Para ilustrar algunos problemas que podríamos tener en este caso específico, simplemente mostraré de nuevo una línea de tiempo. En la prueba, estamos, como, tratando de poner una consulta en el campo de entrada. Así que básicamente, el usuario comenzará a escribir N. Lanzaremos una llamada a la API. Porque el código simplemente está lanzando la llamada a la API tan pronto como actualizamos la consulta. Y luego escribimos la segunda letra. A. Hacemos otra llamada a la API para N.A., luego la tercera letra. Ya entiendes la idea. Si recuerdas el primer ejemplo de línea de tiempo que mostré, el problema que enfrentamos en ese momento fue que las promesas pueden resolverse en desorden. Así que básicamente, ¿qué pasa si resolvemos N.A. primero? Es una posibilidad. Así que básicamente, si resolvemos N.A. primero, obtendremos banana. Porque la implementación
6. Entendiendo el Orden de Resolución de Promesas
Short description:
En segundo lugar, si la primera consulta se resuelve al final, el usuario verá resultados que no coinciden con la consulta. Esto puede compararse con escribir 'París' y obtener resultados para 'Londres'. Es importante abordar este problema ya que puede ocurrir fácilmente en el mundo real debido a factores como el equilibrio de carga y el almacenamiento en caché. Veamos lo que pasamos por alto en nuestra prueba original y lo que encontramos. Creamos una línea de tiempo donde cambiar el orden de los resultados causó el problema. Para solucionar esto, necesitamos cambiar el orden en el que se resuelven las promesas. Presentamos FastCheck.
dirá banana. Luego, si resolvemos N.A. en segundo lugar, todavía tendremos banana. Lo cual está definitivamente bien. Pero el problema es que si resolvemos la primera consulta en el último lugar, obtendremos algo que es un poco extraño. Quiero decir, el usuario habrá escrito N.A.N. y el resultado que el usuario verá no es el correcto. El usuario verá el resultado que no coincide con la consulta. Es un poco como este. Quiero decir, estás escribiendo algo como París y obtienes resultados para Londres. Lo cual obviamente no es lo que quieres como usuario. Y como usuario, si tienes una entrada que se comporta de esa manera, puedes tener algo aún peor. Algo como simplemente bailando todo el tiempo. Cada vez que juegas con una letra, tienes algo que está bailando. Este video ha sido realmente tomado del sitio web oficial. Una vez más, no estoy vinculado a esta empresa. Pero cuando juegas un poco con ella, puedes tener este tipo de comportamiento. Este tipo de problema, justo antes de pasar a la siguiente diapositiva, este tipo de problema puede ocurrir fácilmente en el mundo real. No controlas cómo funcionará tu equilibrio de carga. Así que tal vez tendrás un servidor golpeado por la primera consulta, un segundo servidor para la segunda consulta. Tal vez el resultado para París ha sido almacenado en caché y no el de Londres. Hay muchas formas en las que puedes caer en algo más rápido para una consulta y no para la otra. Y por eso necesitamos asegurarnos de que no caigamos en ese caso. Así que veamos lo que pasamos por alto en nuestra prueba original. Veamos juntos lo que encontramos. Básicamente, lo que se nos ocurrió fue una especie de línea de tiempo. Y en esta línea de tiempo, tengo algo especial. Solo cambie un poco el orden de los resultados. Básicamente, en lugar de resolver N, luego NAs y NAM, simplemente decidí por, diría razón aleatoria decir que N se resolverá al final. Y esta es la razón por la que obtuve el problema reportado si ejecuto la prueba manualmente. Así que la idea será, si pensamos en eso, la idea será cambiar un poco el orden de las promesas y cómo se resuelven, el orden
7. Uso del Marco FastCheck para Llamadas API
Short description:
Soy el autor y principal contribuyente de FastCheck, un marco de pruebas basado en propiedades. Veamos cómo podemos usarlo. Definimos una propiedad que toma generadores y una función lambda para afirmaciones. Ejecutamos la propiedad utilizando los ayudantes de propiedad y afirmación. Confiamos en el marco para manejar las llamadas API de manera determinista.
en el orden en que se resolverán. Así que permítanme presentarles FastCheck. Como hablamos un poco sobre eso antes al comienzo de la masterclass, soy el autor y principal contribuyente de FastCheck. Esta es una captura de pantalla de hace unas semanas. Ha aumentado un poco para la descarga. Estoy bastante contento por eso. Si hay nuevas personas que quieren probar esto, estoy feliz de tener a nuevas personas. Pero es un marco de testing basado en propiedades. No entraré en demasiados detalles sobre las propiedades. Solo daré una breve descripción general. Pero veamos cómo podemos usarlo, básicamente. Así que tenemos nuestra prueba. Así que esta es la prueba que hemos visto juntos inicialmente al comienzo de esta masterclass. Solo conectaremos FastCheck. Como FastCheck es un marco de testing basado en propiedades, necesitamos definir una propiedad. Una propiedad es simplemente algo que toma generadores. En mi caso, es un programador. Quiero programar algo. Y en base a estos generadores, tendré algún tipo de función lambda. Y esta función lambda es la afirmación de lo que quiero ejecutar, básicamente. En mi caso, solo ejecutaré la misma prueba que antes. Pero esta vez, obtengo el parámetro S. El parámetro S es una programación. Lo usaré justo después. Y ahora que tenemos la propiedad, necesito ejecutarla. Así que básicamente, el marco está hecho con dos ayudantes. Tenemos propiedad y tenemos afirmación, que son algo así como ejecutar cosas. Y básicamente, esta es la forma de conectar el marco. Ahora que tenemos el marco lanzado, podemos intentar pedirle al marco que haga algo por nosotros. Así que básicamente, lo que queremos allí es ser capaces de usar el marco y confiar en el marco cada vez que hay una llamada a la API. Así que lo que estoy haciendo allí es que le estoy diciendo al marco, de acuerdo, cada vez que recibas una llamada para sugerencias para, necesitas manejar esa llamada. Y lo que significa es que si hay una llamada, el marco bloqueará esta llamada hasta que considere útil entrar en un
8. Conectando el Marco y Encontrando Errores
Short description:
Y cuando entrará es como cuando le dije que lo hiciera. Es la línea 20. Para conectar el marco, tuve que definir algún tipo de propiedad. La propiedad está hecha de generadores y la función lambda, que es la forma de ejecutar la prueba en sí. El resultado está hecho de un contraejemplo. El marco decidió que el orden no debería ser como el que recibimos inicialmente, sino que intentará algo más. Informa que no funciona. Es un marco de pruebas basado en propiedades similar al fuzzing.
de manera determinista. Y cuando entrará es como cuando le dije que lo hiciera. Es la línea 20. Solo le digo al marco, está bien. Ahora tienes todo listo. Puedes simplemente elegir lo que quieres liberar y cuándo quieres liberar las cosas. Y esto es lo que se hace en la línea 20. Entonces, básicamente, para conectar el marco, tuve que definir algún tipo de propiedad. La propiedad está hecha de generadores y la función lambda, que es la forma de ejecutar la prueba en sí. Tan pronto como obtenemos la programación, puedo programar algunas de las llamadas. Y después de eso, cuando las llamadas se programan, puedo simplemente pedirle al marco que libere todo. Y mi prueba es la misma que antes. Espero tener el mismo resultado, sea cual sea el orden de resultado que obtenga. Ahora que hemos conectado el marco, la pregunta que podemos hacernos es, está bien, es genial, pero ¿funciona? ¿Encontraré un error con eso? Y la cosa es que, sí. Y si retomamos el resultado, obtenemos algunos resultados un poco más complejos que el resultado habitual. Pero el resultado está hecho de un contraejemplo. Entonces, básicamente, el contraejemplo nos está diciendo, está bien, obtuvimos algunas tareas, se planificaron, y el programador quería ejecutarlas. Se le pidió que las ejecutara. Y el programador decidió, en primer lugar, liberar las promesas para NAN. Así que esa es la razón por la que empezamos con NAN. Luego comenzó a liberar NA. Y al final, él quería liberar N. Pero lo que recibimos inicialmente fue N, luego recibimos NA, y luego NAN. Entonces, básicamente, el marco decidió que el orden no debería ser como el que recibimos inicialmente, sino que intentará algo más. Y basándose en este valor, el marco también nos informa que no funciona. Así que, básicamente, en lugar de tener solo banana, obtuve resultados adicionales, que es básicamente lo que ilustramos juntos con la línea de tiempo. Pero podemos llevar las cosas aún más lejos. Así que estaba hablando del hecho de que es un marco de pruebas basado en propiedades. La idea está cerca del fuzzing. Para las personas que saben un poco sobre fuzzing, la forma de hacerlo es empujar las cosas, como pedirle a la computadora que piense en tu prueba, que piense en los casos límite por ti. Así que no quieres escribir los casos límite, quieres que el
9. Mejorando la Prueba y Manejando Eventos Incontrolables
Short description:
Hoy, discutiré cómo mejorar la prueba permitiendo que el marco decida los resultados esperados, la consulta del usuario y el resultado generado. Al precalcular los resultados y permitir que el marco elija la consulta, podemos manejar diferentes escenarios. Además, en lugar de codificar los resultados, podemos generar valores aleatorios. Este enfoque considera al usuario como un evento incontrolable y prueba el código con la escritura del usuario, la resolución de consultas y la escritura del usuario nuevamente.
ordenador para pensar en casos límite por ti. Y hoy en esa prueba, tengo muchas cosas que pueden ser mejoradas un poco para preguntar, para dar más ayuda al marco para decidir por nosotros qué puede o qué no podría hacerse. Así que básicamente, los resultados esperados, podríamos simplemente haberlos calculado. Tenemos todo listo en este lugar para calcular el resultado Sabemos que tenemos todos los posibles resultados en un array. Conocemos la consulta del usuario de antemano. Así que podemos precalcular el resultado con antelación. Este es como normal. Luego tenemos la consulta del usuario. En este momento consideramos que la consulta del usuario siempre será NAM. Pero si cambiamos la consulta del usuario a algo diferente, tal vez el código nunca fallará porque nunca caemos en una condición de carrera. O tal vez caeremos en una condición de carrera, pero no de una manera que rompa la interfaz de usuario. Así que queremos dejar que el marco decida cuál será la consulta. Así que en lugar de codificar esta consulta, la idea es pedir al marco una cadena, cualquier cadena, cualquier cosa. Simplemente pedimos una cadena y tomamos esta cadena, se llama la consulta del usuario y el código funcionará como antes. Entonces también podemos generar el resultado. En lugar de tener resultados codificados, no es genial tener cosas codificadas, básicamente. Esa es la idea detrás de la escena. Podemos simplemente pedir un conjunto de valores aleatorios. Serán nuestros nuevos todos los resultados. Y básicamente la prueba continúa funcionando como antes. Y si recuerdas un poco la definición inicial de condición de carrera, las condiciones de carrera eran problemas de eventos incontrolables. Y te hablé de las llamadas a la API, pero hay otros eventos incontrolables en el navegador. Básicamente el usuario. Nunca sabemos cuándo el usuario hará clic, nunca sabemos cuándo el usuario escribirá. ¿Y adivina qué? En el campo de autocompletar, el usuario puede escribir letras, puede haber algunas consultas que vuelven, pueden escribir otras letras, otras consultas, etc. Y hasta ahora no hemos probado esto. No sabemos si todo el código funcionará si tenemos al usuario escribiendo, consultas resolviéndose, el usuario escribiendo de nuevo. Así que podemos cambiar eso un poco y decir, está bien, quiero que el usuario escriba, quiero que las consultas regresen, pero quiero entrelazar todas ellas juntas en una sola prueba. Y así es como podemos hacer eso. Simplemente podrás retomar la diapositiva más tarde si quieres leer más sobre eso. Y ahí
10. Actualizando la Prueba y Descubriendo Errores
Short description:
Actualizamos nuestra prueba permitiendo que el marco decida la consulta válida del usuario, los resultados y el orden. El marco prueba diferentes escenarios e identifica un caso fallido. Al probar varias entradas de usuario, podemos descubrir errores específicos para ciertas cadenas.
aquí estamos. Así que hemos actualizado nuestra prueba de una manera diferente. No, no codificamos nada. No tenemos una consulta de usuario, no tenemos todos los resultados codificados. Dejamos que el marco decida cuál es la consulta válida del usuario, cuáles son los resultados válidos y cuál es el orden que consideramos correcto. Y el marco simplemente hará su trabajo. Intentará hacer cosas y ver si funciona o si falla en algunos casos. Y en este caso, tengo un caso que está fallando. El marco me está diciendo, está bien, intenté escribir A, luego intenté escribir B. Luego voy a prometer para A, B. Lo resolveré primero. Y luego también voy a consultar por A, y lo resolveré al final. Y con eso, dado que todos los resultados eran solo el array que contiene A, así que solo tengo A como un posible resultado, y el usuario escribió A, B, obtuve una condición de carrera. Así que este es incluso más simple que el que inicialmente propusimos. Pero el punto de este es que va incluso más allá, porque puede probar aún más posibilidades. Probará cualquier tipo de cadena, cualquier tipo de entradas de usuario, y tal vez podamos tener un error
11. Abordando las Condiciones de Carrera y Aleatorizando las Entradas
Short description:
Las condiciones de carrera rompen la confianza del usuario en su aplicación. Reordenar las promesas puede ayudar a solucionarlas, pero es fácil pasar por alto el problema real. Aleatorizar la salida y las entradas es una solución. La biblioteca Fastcheck, utilizada por Jest y Jasmine, puede ayudar a identificar las condiciones de carrera en React.
para una cadena específica. Así que ese es el punto. Si tienes que tener algo en cuenta sobre esta charla, diría que las condiciones de carrera son reales. Diría que rompen la confianza que el usuario puede tener en tu fuente y en tu aplicación, en general. Así que eso es la mayoría de las veces no es tan crítico solucionarlas. Pero si no las solucionas, romperás la confianza que el usuario tiene en ti y en tu aplicación. El truco que usamos es básicamente reordenar. Se puede hacer sin ningún marco. Puedes simplemente jugar con promesas y resolverlas cuando quieras. El problema es que codificarás algo y puedes no codificar lo correcto, y puedes caer fuera del problema real. Así que la solución que estaba presentando allí es como ir a por cosas aleatorias. Así que podemos aleatorizar la salida y la forma en que se resolverá la promesa. Pero también podemos ir más allá y aleatorizar las entradas mismas. Así que ese es el punto de esta charla. Creo que eso es todo para esta charla. Antes de que dejara el micrófono, había como el nombre de la biblioteca es fastcheck, y ya es utilizada internamente por Jest y Jasmine para dar algunos ejemplos. Y también la usé y encontré la condición de carrera en React. Pero esta nunca ha sido fusionada. Así que eso es todo.
12. Equilibrando el Enfoque Metódico con la Aleatorización
Short description:
Tengo una pregunta sobre la aleatorización de la resolución de promesas. ¿Cómo equilibras la necesidad de ser metódico con la aleatorización? El marco permite sembrar el algoritmo, haciendo que las pruebas sean reproducibles. Además, hay una lógica de reducción para simplificar los casos fallidos y reducir la complejidad.
Muchas gracias por tu charla. Definitivamente tengo algunas preguntas. Podría simplemente abrir rápidamente con una, que es, entonces abogas por un enfoque de aleatorización en la forma en que se resuelven las promesas. Algo de eso no me sienta bien. Como quiero ser bastante metódico en la forma en que escribo el código. ¿Cómo equilibras el tipo de, no sé, la necesidad o el deseo del desarrollador de permanecer metódico con básicamente solo aleatorizar hasta que funcione? Diré que es aleatorio de cierta manera. Tienes alguna forma de sembrar el algoritmo. Así que básicamente todo lo que genera el marco está sembrado. Así que en cualquier momento que ejecutes una prueba, puedes reproducir todo. Así que básicamente tienes una semilla. Si está fallando, no mostré mucho en la presentación, pero la prueba es que puedes reproducir la prueba solo basándote en la semilla. Y además de eso, tenemos algún tipo de lógica de reducción, que no te dará el primer caso fallido, sino que intentará reducir el caso a algo muy simple de obtener. Porque la mayoría de las veces, para el ejemplo con cosas de A y B, fue el caso inicial donde probablemente es mucho más complejo. Y el marco dijo, está bien, puedo obtener este problema con algo incluso más pequeño, con menos promesas, menos valor, etc. Así que realmente, sí, se trata realmente de reducir la superficie para entender qué está mal.
QnA
Mitigando las Condiciones de Carrera
Short description:
¡Gracias por las preguntas! La condición de carrera de React que encontré estaba relacionada con suspense y suspense list. Causó un problema de bloqueo donde la lista de suspense no se resolvería. Para mitigar las condiciones de carrera, el enfoque depende del caso. En mi empresa, utilizamos una estrategia de caché para valores disponibles globalmente y actualizaciones en tiempo real. La estabilidad de la salida y la información del backend determinan el enfoque. Aunque puede haber algún parpadeo en la interfaz de usuario, el objetivo es converger a la versión real después de cierto tiempo.
Eso es genial. Muchas gracias por todas las preguntas, gente. Vaya, ahora hay tantas preguntas. Por favor, sigan enviándolas. Pero eso fue rápido. ¿Cuál fue la condición de carrera de React que encontraste? Vaya, buena pregunta. Fue algo alrededor de React. Fue con suspense, suspense list y cosas así. Había algún tipo de orden en el que, dada la resolución de tus suspenses, si estabas en la lista de suspense en algún tipo de modo hacia adelante o cosas así, que todavía, no estoy seguro de si el asunto ha sido lanzado aún, pero terminaste en algún tipo de bloqueo y nunca pudiste liberar, quiero decir, la lista de suspense nunca se resolverá en absoluto. Oh, eso es bastante complicado. Siento que esa va a ser una palabra para encapsular algunas de estas historias. ¿Qué enfoques utilizas para mitigar las condiciones de carrera después de haberlas detectado? Para la presentación, no he mostrado cómo podemos solucionarlo en este ejemplo específico. Creo que depende mucho del caso. Personalmente tengo algunos casos en la empresa donde tenemos una estrategia de caché para almacenar algunos valores que están disponibles globalmente en la aplicación y se actualizan en tiempo real. Realmente creo que depende de vez en vez, depende de lo que quieras, de cuán estable quieras que sea tu salida y cuál es la información
Manejo de la Sobrecarga de Pruebas y la Reproducibilidad
Short description:
En mi caso, la interfaz de usuario puede parpadear un poco, pero siempre convergerá a la versión real. El marco ejecuta la afirmación 100 veces por defecto, permitiéndote reducir o personalizar el número de ejecuciones. La sobrecarga es limitada, ya que el código de generación se mantiene simple. 100 ejecuciones son generalmente suficientes para encontrar muchos errores, pero casos específicos pueden requerir pruebas más frecuentes. Diferentes ejecuciones de un conjunto de pruebas utilizando cadenas aleatorias usarán diferentes cadenas cada vez, facilitando la detección de nuevos errores.
obtienes de, por ejemplo, el backend. En mi caso, lo siento por, no tengo ninguna versión número, por lo que no puedo confiar en, está bien, esta es la última versión de, esta es una anterior. Así que puede que tenga algunos casos en los que la interfaz de usuario puede parpadear un poco, digamos, pero en la regla que quiero en la interfaz de usuario es que al final, después de un cierto tiempo, siempre convergerá a algo que es la versión real.
Interesante. Genial. Esta es una gran pregunta. ¿Hay alguna sobrecarga o cuál es la sobrecarga? ¿Puedes controlar esto y cuántas iteraciones o permutaciones deberías o puedes o has generado? Por defecto, el marco simplemente ejecutará 100 veces la afirmación. La idea no es ejecutar todo porque el alcance de las posibilidades es infinito porque estamos pensando en cualquier tipo de consulta de usuario, cualquier tipo de resultado. Así que básicamente, el marco simplemente está diciendo, está bien, probemos 100 de ellos. Si falla, simplemente intentará reducir y la sobrecarga es como si ejecutaras la prueba 100 veces pero puedes reducir eso, puedes cambiar el número de ejecuciones que quieres para tu prueba si lo necesitas. Para la sobrecarga, diría que es el coste de generar el valor pero normalmente, debería ser bastante limitado porque intento no poner tanta complejidad en el código que está haciendo la generación. Quiero decir, la idea es ser lo más libre posible para hacer la generación de cosas pero todavía tiene una sobrecarga.
Si el valor por defecto es 100, ¿100 es un buen número para empezar? ¿Funciona eso en la mayoría de los casos? Sí, inicialmente, me sorprendió un poco cuando empecé a hacer eso. Así que las propiedades basadas en la técnica no están relacionadas con JavaScript en absoluto. Vino de Haskell u otras palabras y básicamente, me sorprendió un poco que 100 ejecuciones pudieran encontrar algo y cuando lo intenté en realidad con 100 ejecuciones, está bastante bien para encontrar muchos errores. Si es un caso muy específico de borde, probablemente no caerás en él en 100 ejecuciones pero en ese caso, tienes algo muy especial para probar y tal vez quieras ejecutarlo más a menudo para lanzarlo en más pruebas. Sí, seguro. Así que 100 se siente bien para muchos casos de uso. Sí, y tendrás tu CI que lo ejecutará, etc. Así que podrás ver. Siento que depende es como una respuesta bastante segura para esta. Sí. Sí, sí, sí. Vale. ¿Las diferentes ejecuciones de un conjunto de pruebas utilizando cadenas aleatorias usarán diferentes cadenas cada vez, como todas las diferentes ejecuciones? Parece que podría ser difícil reproducir los fallos aunque. Esa es una buena pregunta. A menudo me hacen esta. Básicamente, por defecto, estoy diciendo por defecto, para ver esto como si se cambiara todo el tiempo. Así que cada vez que ejecutes la prueba, tendrás una nueva semilla, por lo que significa que se producirán nuevas cadenas. Y posiblemente
Estabilidad y Falsos Positivos en las Pruebas
Short description:
El marco está diseñado para encontrar casos límite clásicos y no debería ser inestable. Sin embargo, puede haber casos raros en los que falle. Los falsos positivos pueden ocurrir si las condiciones para una carrera son muy raras y dependen de combinaciones específicas de factores.
de una ejecución a otra, podrías tener nuevos errores detectados. La filosofía detrás de esto es que no quieres ningún error en tu aplicación. Así que si encuentra un error, básicamente, tal vez solo quieras arreglarlo. Y después de eso, tienes como, podría ser difícil de reproducir esa parte. Tenemos una semilla que se imprimirá en la salida y puedes tomarla. Sí. Así que puedes reproducir la ejecución utilizando la misma semilla. Eso es lo que asumí que sería el caso. Pero, ¿no significa eso que estas pruebas son inestables? ¿Qué pasa si el error solo ocurre en uno de muchos órdenes de devoluciones? Siento que de alguna manera respondiste a esto en la última. Sí, normalmente. Lo he usado en producción durante años y en mi empresa. Así que, cuando pensamos en eso, fue como, tal vez será inestable todo el tiempo. Pero en realidad, es bastante estable. Excepto si haces un código que está haciendo cosas muy específicas de una manera muy extraña. Pero la mayoría de las veces, si no encuentra el problema de inmediato, simplemente nunca encontrará ningún problema. Quiero decir, depende de cuánta confianza tengas en tu código y cuántos casos límite pongas en el código. Pero básicamente, el marco está tratando de encontrar casos límite clásicos. Así que, por ejemplo, los valores pequeños se generarán más a menudo. Si generas un array, posiblemente habrá alguna colisión entre los valores más a menudo que en cosas puramente aleatorias, etc. Así que se supone que debe encontrar el error bastante rápido. Y esa es la razón por la que normalmente no debería ser inestable. Pero no puedo decir que no sea inestable porque puede suceder de vez en cuando.
Sí, es un tema complicado, ¿no es así? Porque no estás ejecutando la suite de pruebas bajo las mismas condiciones exactas cada vez. Hay diferencias. Pero en teoría, son casos razonablemente realistas. Entonces, si falla, ¿qué? Siento que esto está en el mismo ámbito de preguntas, pero ¿existe la posibilidad de que nunca haga una prueba solo siendo un falso positivo, tal vez porque no lo has ejecutado suficientes veces? Sí, puedes tener falsos positivos. Así que básicamente, fusionas algo, sientes que funciona. Por ejemplo, recientemente trabajé en alguna condición de carrera en la caché. Así que la condición
Pruebas con el marco vTest
Short description:
Al ejecutar pruebas en CI, los falsos positivos pueden identificarse y revertirse rápidamente si la prueba es nueva. Se planteó una pregunta sobre la pronunciación de 'vTest' o 'vitest', y se decidió colectivamente que sería 'vTest'. El código de prueba mostrado se puede usar dentro de las pruebas existentes de Jest sin ninguna vinculación de marco. El orador también mencionó tener vinculaciones para marcos específicos como Jest y vTest, pero no son necesarios si se usa la sintaxis .assert.property.
para la carrera fue muy, muy raro. Depende de la combinación de muchas cosas. Fue un poco difícil, por lo que fue difícil encontrarlo. Entonces sí, diría que puedes tener falsos positivos. Y cuando lo ejecutas en CI, verás el problema de inmediato. Entonces puedes revertirlo si la prueba es nueva. Entonces normalmente debería ser bastante rápido ver el problema.
Sí. Sí. Esta es una pregunta. Ayer, en la masterclass de testing JS Summit, hice este comentario justo al principio donde no sabía si era vTest o vitest. El grupo llegó colectivamente a una decisión, y ahora no puedo recordar cuál es. ¿Funciona bien con vTest? Verás, yo habría optado por defecto por vitest. Y luego porque es VT, ¿no es así? Es VT, así que tiene que ser vTest. Gracias. Sí, definitivamente. No hay vinculación con ningún marco. Entonces básicamente, la prueba que te he mostrado está justo dentro de una prueba existente de Jest. Solo usamos la prueba clásica de Jest. Es solo una construcción dentro de ella. Entonces puedes poner el mismo código exacto dentro de vTest. No sé cómo quieres pronunciarlo. Es vTest. Es vTest. He oído vTest. Y tengo algunas vinculaciones para frameworks específicos. Entonces básicamente, tengo uno para Jest, para que puedas hacer algo como it.props. Para vTest, también tengo uno, pero quiero evolucionarlo un poco con v1. Pero básicamente, normalmente, no deberías necesitar nada. Quiero decir, si estás de acuerdo con escribir .assert.property, funcionará bien.
Ubicación de la Fuente del Marco y Preguntas y Respuestas
Short description:
¿Este marco ayuda a localizar la fuente de las condiciones? Tenemos una sección de preguntas y respuestas con el orador para conversaciones cara a cara. Por favor, proporciona más información para preguntas sin respuesta. Tenemos un breve descanso antes de continuar.
Sí, genial. Muchas gracias también por tu aporte. Creo que probablemente tenemos un breve momento para solo esto. Entonces, ¿este marco te ayuda a localizar la fuente de las condiciones? No entiendo exactamente a qué nos referimos con la fuente de la condición, pero en realidad, lo he leído en voz alta y tampoco sé lo que significa. ¿Sabes qué? Estamos literalmente justo en ese momento en el que el tiempo está a punto de llegar a cero. Así que en realidad, es mi momento de recordarte que justo al lado de la entrada está la sección de preguntas y respuestas con el orador donde podemos tener más conversaciones cara a cara con Nicola y nosotros y también en línea. Puedes ir allí en persona. Puedes ir allí. Y si eres el originador de esta pregunta, me encantaría un poco más de información porque la leí inicialmente. Estoy como, sí, no, lo entiendo. Y ahora estoy un poco también. Asegurémonos de responder las preguntas que la gente hace. Todavía tenemos. Hay tantas preguntas que no tuvimos tiempo de cubrir. Así que por favor utiliza la sección de preguntas y respuestas con el orador. Tenemos un descanso muy corto donde puedes elegir entre quedarte aquí o ir al otro espacio. Si puedo recuperar mis diapositivas sería maravilloso, gente en la parte de atrás de la sala. Muchas gracias en efecto.
This Talk discusses modern web debugging and the latest updates in Chrome DevTools. It highlights new features that help pinpoint issues quicker, improved file visibility and source mapping, and ignoring and configuring files. The Breakpoints panel in DevTools has been redesigned for easier access and management. The Talk also covers the challenges of debugging with source maps and the efforts to standardize the source map format. Lastly, it provides tips for improving productivity with DevTools and emphasizes the importance of reporting bugs and using source maps for debugging production code.
Cecilia Martinez, a technical account manager at Cypress, discusses network requests in Cypress and demonstrates commands like cydot request and SCI.INTERCEPT. She also explains dynamic matching and aliasing, network stubbing, and the pros and cons of using real server responses versus stubbing. The talk covers logging request responses, testing front-end and backend API, handling list length and DOM traversal, lazy loading, and provides resources for beginners to learn Cypress.
Testing Pyramid Makes Little Sense, What We Can Use Instead
Top Content
Featured Video
2 authors
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.
Today's Talk discusses the future of performance tooling, focusing on user-centric, actionable, and contextual approaches. The introduction highlights Adi Osmani's expertise in performance tools and his passion for DevTools features. The Talk explores the integration of user flows into DevTools and Lighthouse, enabling performance measurement and optimization. It also showcases the import/export feature for user flows and the collaboration potential with Lighthouse. The Talk further delves into the use of flows with other tools like web page test and Cypress, offering cross-browser testing capabilities. The actionable aspect emphasizes the importance of metrics like Interaction to Next Paint and Total Blocking Time, as well as the improvements in Lighthouse and performance debugging tools. Lastly, the Talk emphasizes the iterative nature of performance improvement and the user-centric, actionable, and contextual future of performance tooling.
Cypress is a powerful tool for end-to-end testing and API testing. It provides instant feedback on test errors and allows tests to be run inside the browser. Cypress enables testing at both the application and network layers, making it easier to reach different edge cases. With features like AppActions and component testing, Cypress allows for comprehensive testing of individual components and the entire application. Join the workshops to learn more about full circle testing with Cypress.
This Talk introduces Test Effective Development, a new approach to testing that aims to make companies more cost-effective. The speaker shares their personal journey of improving code quality and reducing bugs through smarter testing strategies. They discuss the importance of finding a balance between testing confidence and efficiency and introduce the concepts of isolated and integrated testing. The speaker also suggests different testing strategies based on the size of the application and emphasizes the need to choose cost-effective testing approaches based on the specific project requirements.
ReactJS es extremadamente popular y, por lo tanto, ampliamente soportado. TypeScript está ganando popularidad y, por lo tanto, cada vez más soportado.
¿Los dos juntos? No tanto. Dado que ambos cambian rápidamente, es difícil encontrar materiales de aprendizaje precisos.
¿React+TypeScript, con los IDEs de JetBrains? Esa combinación de tres partes es el tema de esta serie. Mostraremos un poco sobre mucho. Es decir, los pasos clave para ser productivo, en el IDE, para proyectos de React utilizando TypeScript. En el camino, mostraremos el desarrollo guiado por pruebas y enfatizaremos consejos y trucos en el IDE.
TypeScript no es solo tipos e interfaces. Únete a esta masterclass para dominar características más avanzadas de TypeScript que harán tu código a prueba de balas. Cubriremos tipos condicionales y notación de inferencia, cadenas de plantillas y cómo mapear sobre tipos de unión y propiedades de objetos/arrays. Cada tema se demostrará en una aplicación de muestra que se escribió con tipos básicos o sin tipos en absoluto y juntos mejoraremos el código para que te familiarices más con cada característica y puedas llevar este nuevo conocimiento directamente a tus proyectos. Aprenderás:- - ¿Qué son los tipos condicionales y la notación de inferencia?- ¿Qué son las cadenas de plantillas?- Cómo mapear sobre tipos de unión y propiedades de objetos/arrays.
La Biblioteca de Pruebas de React es un gran marco para las pruebas de componentes de React porque responde muchas preguntas por ti, por lo que no necesitas preocuparte por esas preguntas. Pero eso no significa que las pruebas sean fáciles. Todavía hay muchas preguntas que tienes que resolver por ti mismo: ¿Cuántas pruebas de componentes debes escribir vs pruebas de extremo a extremo o pruebas de unidad de nivel inferior? ¿Cómo puedes probar una cierta línea de código que es difícil de probar? ¿Y qué se supone que debes hacer con esa persistente advertencia de act()? En esta masterclass de tres horas, presentaremos la Biblioteca de Pruebas de React junto con un modelo mental de cómo pensar en el diseño de tus pruebas de componentes. Este modelo mental te ayudará a ver cómo probar cada bit de lógica, si debes o no simular dependencias, y ayudará a mejorar el diseño de tus componentes. Te irás con las herramientas, técnicas y principios que necesitas para implementar pruebas de componentes de bajo costo y alto valor. Tabla de contenidos- Los diferentes tipos de pruebas de aplicaciones de React, y dónde encajan las pruebas de componentes- Un modelo mental para pensar en las entradas y salidas de los componentes que pruebas- Opciones para seleccionar elementos DOM para verificar e interactuar con ellos- El valor de los mocks y por qué no deben evitarse- Los desafíos con la asincronía en las pruebas de RTL y cómo manejarlos Requisitos previos- Familiaridad con la construcción de aplicaciones con React- Experiencia básica escribiendo pruebas automatizadas con Jest u otro marco de pruebas unitarias- No necesitas ninguna experiencia con la Biblioteca de Pruebas de React- Configuración de la máquina: Node LTS, Yarn
La web ha evolucionado. Finalmente, también lo ha hecho el testing. Cypress es una herramienta de testing moderna que responde a las necesidades de testing de las aplicaciones web modernas. Ha ganado mucha popularidad en los últimos años, obteniendo reconocimiento a nivel mundial. Si has estado esperando aprender Cypress, ¡no esperes más! Filip Hric te guiará a través de los primeros pasos sobre cómo empezar a usar Cypress y configurar tu propio proyecto. La buena noticia es que aprender Cypress es increíblemente fácil. Escribirás tu primer test en poco tiempo y luego descubrirás cómo escribir un test de extremo a extremo completo para una aplicación web moderna. Aprenderás conceptos fundamentales como la capacidad de reintentar. Descubre cómo trabajar e interactuar con tu aplicación y aprende cómo combinar pruebas de API y de UI. A lo largo de todo este masterclass, escribiremos código y realizaremos ejercicios prácticos. Saldrás con una experiencia práctica que podrás aplicar a tu propio proyecto.
Sumérgete en el mundo de la IA con nuestro masterclass interactivo diseñado específicamente para desarrolladores web. "Masterclass: Integrando LangChain con JavaScript para Desarrolladores Web" ofrece una oportunidad única para cerrar la brecha entre la IA y el desarrollo web. A pesar de la prominencia de Python en el desarrollo de IA, el vasto potencial de JavaScript sigue siendo en gran medida inexplorado. Este masterclass tiene como objetivo cambiar eso.A lo largo de esta sesión práctica, los participantes aprenderán cómo aprovechar LangChain, una herramienta diseñada para hacer que los modelos de lenguaje grandes sean más accesibles y útiles, para construir agentes de IA dinámicos directamente dentro de entornos JavaScript. Este enfoque abre nuevas posibilidades para mejorar las aplicaciones web con funciones inteligentes, desde el soporte al cliente automatizado hasta la generación de contenido y más.Comenzaremos con los conceptos básicos de LangChain y los modelos de IA, asegurando una base sólida incluso para aquellos nuevos en IA. A partir de ahí, nos sumergiremos en ejercicios prácticos que demuestran cómo integrar estas tecnologías en proyectos reales de JavaScript. Los participantes trabajarán en ejemplos, enfrentando y superando los desafíos de hacer que la IA funcione sin problemas en la web.Este masterclass es más que una experiencia de aprendizaje; es una oportunidad de estar a la vanguardia de un campo emergente. Al final, los asistentes no solo habrán adquirido habilidades valiosas, sino que también habrán creado funciones mejoradas con IA que podrán llevar a sus proyectos o lugares de trabajo.Ya seas un desarrollador web experimentado curioso acerca de la IA o estés buscando expandir tus habilidades en áreas nuevas y emocionantes, "Masterclass: Integrando LangChain con JavaScript para Desarrolladores Web" es tu puerta de entrada al futuro del desarrollo web. Únete a nosotros para desbloquear el potencial de la IA en tus proyectos web, haciéndolos más inteligentes, interactivos y atractivos para los usuarios.
A diferencia de las pruebas unitarias, las pruebas de extremo a extremo buscan interactuar con su aplicación tal como lo haría un usuario real. Y como todos sabemos, puede ser bastante desafiante. Especialmente cuando hablamos de aplicaciones móviles. Las pruebas dependen de muchas condiciones y se consideran lentas e inestables. Por otro lado, las pruebas de extremo a extremo pueden dar la mayor confianza de que su aplicación está funcionando. Y si se hace correctamente, puede convertirse en una herramienta increíble para aumentar la velocidad del desarrollador. Detox es un marco de pruebas de extremo a extremo en caja gris para aplicaciones móviles. Desarrollado por Wix para resolver el problema de la lentitud e inestabilidad y utilizado por React Native en sí como su herramienta de pruebas E2E. Únete a mí en esta masterclass para aprender cómo hacer que tus pruebas de extremo a extremo móviles con Detox sean excelentes. Prerrequisitos- iOS/Android: MacOS Catalina o más reciente- Solo Android: Linux- Instalar antes de la masterclass
Comments