Pruebas que te ayudan a encontrar defectos más rápido

Rate this content
Bookmark

Esta charla trata sobre los errores comunes que cometen las personas al escribir pruebas.


Mezclar múltiples aspectos dentro de las pruebas es tentador porque puede parecer que se está pintando todo el panorama. Sin embargo, esto oculta la causa raíz cuando una prueba falla. Los métodos de configuración son geniales, pero cuando los desarrolladores se centran demasiado en mantener sus pruebas DRY, pueden llevar fácilmente a la interdependencia de las pruebas. Por lo tanto, algunos principios que hemos aprendido para construir nuestro software debemos desaprenderlos cuando se trata de las pruebas.


La charla destaca otros aspectos como las pruebas infladas que dificultan comprender de qué se tratan y el uso adecuado de las afirmaciones para obtener mejores mensajes de error.

Especialmente si no trabajas con TDD, puede ser fácil crear una prueba que parezca buena pero que te obstaculice cuando falla.


La charla analizará los cuatro escenarios que mencioné anteriormente, explicará por qué tiene sentido pensar en ellos y ofrecerá sugerencias prácticas sobre cómo mejorar las pruebas.

21 min
19 Nov, 2021

Video Summary and Transcription

Esta charla aborda pruebas que ayudan a encontrar defectos más rápido, centrándose en las afirmaciones de casos de prueba, mejorando el contexto de falla de las pruebas, la estructura del código de prueba y los peligros de extraer código en las pruebas. Se enfatiza la importancia de las pruebas pequeñas, el aislamiento de las pruebas y el uso de TDD. Se discuten los beneficios de TDD y la automatización probable, junto con la configuración de un flujo de trabajo de ingeniería y el uso de simulación. En general, la charla proporciona información valiosa sobre cómo escribir pruebas efectivas y garantizar la calidad del código.

Available in English

1. Introducción a la Charla

Short description:

Bienvenidos a mi charla sobre pruebas que te ayudan a encontrar defectos más rápido. Soy Philip, CTO en Oution, y he aprendido de mis propios errores al escribir pruebas. Comenzaré discutiendo lo que esta charla no cubrirá, como la nomenclatura de las pruebas y el número de afirmaciones en un caso de prueba. Tanto los estilos Rspec como BDD son igualmente buenos, es cuestión de preferencia personal.

¡Hola y bienvenidos a mi charla, pruebas que te ayudan a encontrar defectos más rápido! Mi nombre es Philip, pero todos me llaman Phil. Así que tú también puedes hacerlo. Vivo en una ciudad llamada Potsdam en Alemania, justo al lado de Berlín. Pero aparte de los hipsters, también tenemos castillos. También soy CTO de una empresa llamada Oution y he ocupado roles de liderazgo técnico en los últimos años. He sido mentor de varios desarrolladores menos experimentados en el camino.

Y al hacerlo, he aprendido sobre los diferentes errores que cometen las personas y los problemas en los que se meten al escribir pruebas de software. Como disfruto mucho escribir pruebas, soy un gran fanático de TDD, porque me ayuda a organizarme y trabajar en pequeños pasos. Pensé que esta sería una buena oportunidad para compartir algunos de esos conocimientos. Obviamente, yo mismo he cometido la mayoría de esos errores en los últimos años, lo suficiente como para analizarlos y ver qué es realmente importante y qué no lo es. Lo cual me lleva también a mi primer punto. Me gustaría comenzar esta charla no con un tema, sino con los temas que no se tratarán en esta charla. Y lo primero será la nomenclatura de las pruebas, ¿verdad? Hay varios estilos diferentes para escribir nombres de pruebas y descripciones de pruebas. Solo para darte un ejemplo, voy a ejecutar algunos aquí para que veas cómo se ven en un ejecutor de pruebas. Por ejemplo, hay un estilo llamado Rspec, donde básicamente lees todos los describe hasta el it, y luego esto forma una oración completa. Por ejemplo, aquí se puede identificar a un usuario. Esta es una forma de hacerlo, obviamente, ¿verdad? También hay un estilo diferente, BDD, Desarrollo Guiado por el Comportamiento, donde se usa mucho la palabra clave should, así que aquí he usado usuario simplemente como un nombre para un grupo. Y luego el nombre de la prueba debería ser posible identificar a un usuario. Ahora, el punto importante aquí es que ambos son igualmente buenos, ¿verdad? No hay uno mejor que el otro. Es solo una cuestión de gusto personal, lo que te gusta más, lo que funciona para ti. Por eso no quiero hacer un problema de esto aquí. En esta charla voy a usar mucho el estilo BDD, should, pero no creo que sea mejor si prefieres escribir tus pruebas de manera diferente. Eso está perfectamente bien, así que eso no es realmente de lo que trata esta charla.

2. La Importancia de las Afirmaciones en los Casos de Prueba

Short description:

Esta charla no trata de reglas arbitrarias para el número de afirmaciones en un caso de prueba. Hay pros y contras en el uso de una o varias afirmaciones. Es importante encontrar un enfoque que funcione para ti. Los ejemplos utilizados son intencionalmente simples para ilustrar los puntos principales.

Lo segundo de lo que trata esta charla no es sobre ciertas reglas arbitrarias cuando se trata de cuántas afirmaciones deberían haber en un caso de prueba, ¿verdad? Hay reglas vinculadas que dicen que cada prueba solo debe tener una afirmación y no creo que siempre sea, ya sabes, correcto. Por ejemplo, estos dos son exactamente iguales. El primero usa una afirmación donde, ya sabes, queremos afirmar que un objeto de usuario tiene cierta estructura, por lo que podemos usar el objeto de coincidencia para comparar todas esas propiedades. Y si algo falta, entonces falla, pero podríamos escribir la misma prueba exacta también con dos afirmaciones donde verificamos las propiedades individualmente. Probablemente haya pros y contras en cualquiera de estos enfoques, pero no diría, ya sabes, que uno es particularmente mejor o uno es peor. Así que también aquí, ya sabes, esto no es algo de lo que me gustaría hablar. Encuentra algo que funcione para ti y sigue con eso, ¿verdad? Y obviamente... entonces de lo que tampoco trata esta charla es de, espero, de buscarle problemas a mi ejemplo. He elegido ejemplos deliberadamente simples para, ya sabes, transmitir la idea general. Obviamente no son del mundo real, ¿verdad? Probablemente no los encontrarías exactamente así en un escenario del mundo real, a veces incluso pueden contradecir ciertas reglas que menciono, pero siempre es para, ya sabes, transmitir mejor el punto del que estoy hablando.

3. Estructura General de las Pruebas y Uso de Afirmaciones

Short description:

¡Vamos directo al grano! La primera parte se centra en la estructura general de las pruebas y las trampas comunes. Cada prueba debe cubrir un caso de uso. Divida las pruebas que combinan demasiado. Agregue una tercera prueba para la conexión. Incluso en TDD, evite agrupar múltiples casos de uso en una sola prueba. Lo segundo es el uso de afirmaciones. Expresa todo como una expresión booleana. Verifica si una propiedad del usuario tiene el nombre correcto.

De acuerdo, con el terreno nivelado, vamos directo al grano y he estructurado esta charla en dos partes separadas. La primera parte se centra en la estructura general de las pruebas, como organizar todo. Y luego la segunda parte es, ya sabes, cómo realmente escribir pruebas y, ya sabes, dos trampas comunes en las que la gente cae.

Entonces, comencemos con lo primero que veo que sucede mucho y también déjame señalar mi ejecutor de pruebas. Estoy en eso. Y esto es mientras no creo que deba haber solo una afirmación, solo una afirmación en una prueba, lo que sí creo es que cada prueba debe cubrir exactamente un caso de uso. Este es un error que puedes cometer muy fácilmente.

Por ejemplo, aquí, la descripción de la prueba y realmente solo enfócate en la descripción de la prueba aquí, debería ser posible leer desde y escribir en la base de datos. Ahora, y vemos que esta prueba falla. Si te preguntara, ya sabes, ¿qué es? ¿Es la parte de lectura o la parte de escritura? Probablemente no podrías decirlo de memoria, ¿verdad? Y también, si estás trabajando, ya sabes, en tu software y esta prueba, ya sabes, comienza a fallar nuevamente, también necesitas averiguar, ya sabes, qué parte es la que acabas de romper, ¿verdad?

Mi regla general aquí es que siempre que escribas las palabras `y` y `o` en la descripción de una prueba, simplemente haz dos pruebas, ¿verdad? Ya estás combinando demasiado en ese momento, lo cual, ya sabes, no debería combinarse. Entonces, ¿qué podemos hacer al respecto? Ya sabes, podemos dividirlo y déjame, ya sabes, volver a señalar mi ejecutor de pruebas nuevamente. Ahora tenemos dos pruebas. Una debería ser posible leer desde la base de datos. La otra es que debería ser posible escribir en la base de datos. Ahora, si la segunda falla, sabemos, está definitivamente relacionada con la parte de escritura. Eso está roto. No es la parte de lectura. Eso es bueno porque, ya sabes, desde el fallo de la prueba, podemos ver qué está sucediendo.

Sin embargo, queda una pequeña mejora por hacer aquí. ¿Qué sucede, por ejemplo, si ambas fallan? Porque aquí podemos ver que los casos de uso no necesariamente solo se limitan a la palabra clave `y` como la única cosa a tener en cuenta. Si lo piensas, ¿qué necesitan tanto la lectura como la escritura en la base de datos? Entonces, si ambas fallan, podría ser que haya problemas separados. Podría ser simplemente que la conexión no está funcionando. Esta sería la última mejora que haría, agregar una tercera prueba que solo busque la conexión. Entonces, ya sabes, si la prueba de conexión falla, y la de lectura y escritura también, está definitivamente relacionado con la conexión. Definitivamente hay un problema allí, y es muy probable que esto también afecte los aspectos de lectura y escritura, mientras que esto no está tan claro si no tienes esa especificación.

Y algunos de ustedes ahora podrían estar pensando, ya sabes, si haces TDD, esto es algo que, ya sabes, esta estructura viene de manera natural, porque si comienzas a construir esta interfaz, definitivamente comenzarías asegurándote de que haya una conexión a la base de datos. Esta sería la primera prueba que escribirías, y luego agregarías otras pruebas después de ese hecho. Sin embargo, incluso si haces TDD, a veces te dejas llevar, ya sabes, si quieres lograr algo, y es entonces cuando comienzas a agrupar múltiples casos de uso en una sola prueba, esto te afectará más adelante. La segunda cosa de la que me gustaría hablar en cuanto a la estructura general de las pruebas es el uso de afirmaciones, ¿verdad? Y la trampa en la que puedes caer aquí es que esencialmente podemos expresar todo como una expresión booleana, como hacer una verificación verdadera o falsa, ¿verdad? He comenzado aquí, déjame omitir esa segunda prueba por ahora. He comenzado aquí verificando si una cierta propiedad de un usuario tiene el nombre correcto.

4. Mejorando el Contexto de Fallo de las Pruebas

Short description:

Permíteme señalar mi ejecutor de pruebas a esta prueba para verla fallar. La prueba actual verifica lo correcto, pero carece de contexto cuando falla. Al utilizar afirmaciones con comprobaciones de propiedades, podemos proporcionar más contexto para comprender por qué falló la prueba y qué cambios podrían haber causado el error.

Permíteme, ya sabes, señalar mi ejecutor de pruebas para que podamos ver que falle. Ahora, si, ya sabes, esa prueba está bien, ¿verdad? Verifica lo correcto, ¿verdad? Simplemente lo hace de una manera que si falla, no nos dice realmente qué está sucediendo, ¿verdad? Ahora puedes ver que la prueba simplemente nos dice que esperaba verdadero, pero recibió falso. Entonces, ¿qué significa eso? ¿Verdad? Esto nos obliga a abrir el editor y navegar hasta el archivo de prueba para, ya sabes, averiguar qué está sucediendo aquí. Sin embargo, podemos, ya sabes, hacerlo mejor. Podemos, por ejemplo, utilizar la afirmación para tener una propiedad, decir la cosa y hacer que nuestra prueba se vea así. Ahora esperamos que un objeto de usuario tenga una propiedad llamada John, ¿verdad? Y ahora el mensaje de error se ve, ya sabes, ligeramente diferente, ¿verdad? En primer lugar, nos dice que está buscando una cierta ruta aquí llamada nombre. Luego nos dice que esperaba un valor llamado John, pero obtuvo Jane, ¿verdad? Y esto nos brinda contexto, ¿verdad? Entonces, esto no solo nos dice que la prueba, que esperemos tenga un nombre agradable, falla, sino que también nos brinda algo de contexto sobre por qué falló, ¿verdad? Y esto, a su vez, ya sabes, te ayuda a comprender más rápido, ya sabes, qué hiciste recientemente, cómo se relaciona tal vez con este error para que puedas averiguar qué podría, ya sabes, estar causando esto, ya sabes, ¿qué cambiaste que causa este error? Otra cosa común que podemos hacer es, por ejemplo, probar errores, ¿verdad? A veces lanzas excepciones y quieres asegurarte de que se lancen las excepciones correctas, no puedes hacerlo de esta manera, ¿verdad? Entonces tienes tu código, llamas a la función que esperas que lance una excepción, capturas el error, y luego haces alguna afirmación sobre los mensajes de error.

5. Mejorando la Estructura del Código de Prueba

Short description:

Quieres asegurarte de que tu mensaje de error esté incluido en la salida de error. Jest ofrece una afirmación que lanza una función y espera un mensaje de error específico. Proporciona más contexto para trabajar con tu código y solucionar errores. Jest DOM y la biblioteca de pruebas son adiciones útiles a Jest, que te permiten verificar varios estados y atributos de la interfaz de usuario. En lugar de utilizar condiciones booleanas complejas, elige la afirmación que mejor se adapte a tus necesidades. La primera mitad cubrió la estructura general de las pruebas, las afirmaciones y trabajar con un caso de uso a la vez. Ahora examinemos algo de código de prueba. Extraer las interacciones en métodos puede hacer que la estructura de la prueba sea más clara y fácil de entender. Ten cuidado con las interacciones y afirmaciones innecesarias, especialmente al copiar pruebas. Escribir pruebas desde cero y evitar copiar y pegar puede evitar casos de prueba inflados.

Solo quieres asegurarte de que, ya sabes, alguna parte de ese mensaje de error porque los errores, ya sabes, también agregan algún estándar al frente, por ejemplo, un error de dos puntos y solo quieres asegurarte de que tu mensaje de error esté ahí, ¿verdad? Y podemos hacer esto, ya sabes, con un índice de comprobación. Y luego, ya sabes, no queremos que sea menos uno porque significaría que no está ahí. Sin embargo, nuevamente, ese mensaje de error esperado no menos uno no nos ayuda mucho.

Nuevamente, afortunadamente para nosotros, Jest como un marco de pruebas que estoy usando aquí nos ofrece una afirmación que simplemente pasa una función que queremos lanzar y espera que lance un cierto mensaje de error. Ahora, nuevamente, la salida de error se ve ligeramente diferente. En primer lugar, vemos lo que esperábamos. Ahora vemos lo que recibimos en su lugar, mensaje personalizado. Y también nos señala directamente desde dónde se lanzó el error. Y esto puede, ya sabes, una vez más, darte más contexto para trabajar con tu código. Y luego solucionar ese error, con suerte.

Hay, ya sabes, probablemente muchos de ustedes que trabajan con DOM. Algunos de ustedes podrían estar trabajando con la biblioteca de pruebas. Y hay adiciones muy buenas a Jest. Jest DOM es una de ellas. Si estás trabajando con la biblioteca de pruebas, eso te brinda un montón de afirmaciones personalizadas para verificar los atributos de accesibilidad, los estados de la interfaz de usuario, habilitado, deshabilitado, habilitado, enfoque, todo este tipo de cosas. Pero todo esto cae en la misma categoría, ¿verdad? Mi sugerencia general sería, ya sabes, elige la afirmación que se acerque más a lo que realmente quieres hacer, ya sea que quieras verificar una propiedad, que quieras verificar un error, que quieras verificar un cierto estado de la interfaz de usuario, y luego ve con eso, ya sabes, en lugar de simplemente construir alguna forma de condición booleana y luego verificar que sea verdadera o falsa porque eso no te dará mucho.

Ok, esto concluye básicamente la primera mitad, ¿verdad? Estructura general de las pruebas. Hablamos de las afirmaciones y las descripciones de las pruebas y especialmente, ya sabes, trabajar solo con un caso de uso a la vez. Ahora veamos algo de código de prueba, ¿de acuerdo? Por ejemplo, esta prueba, funciona perfectamente. Sin embargo, hay mucho sucediendo aquí, ¿verdad? Entonces, básicamente esta prueba solo verifica que si cambiamos una entrada, nuestro controlador onChange se llame con la propiedad correcta. Pero, ya sabes, tenemos mucha configuración, muchas, ya sabes, interacciones sucediendo aquí abajo. Y la pregunta que haría es, ya sabes, ¿todas estas interacciones son necesarias? Y podría ser, ¿verdad? Y si es necesario, entonces en lugar de simplemente, ya sabes, escribirlo aquí, yo, ya sabes, seguiría adelante y extraería eso, por ejemplo, en un método, llámalo, por ejemplo, simulateChange, que tiene un valor. Y luego puedo mover esto aquí abajo, o simulateChange en su lugar. Entonces, toda la estructura de preparación, acción, estructura de esa prueba se volvió mucho, ya sabes, más limpia, ¿verdad? Y también esto tiene un nombre, ¿verdad? Queremos simular el cambio porque de eso se trataba este bloque, ¿verdad? Ahora, al extraerlo al método, darle a ese método un nombre adecuado, podemos simplemente hacer esto más claro para el lector. Sin embargo, veo mucho más. Por ejemplo, hay un onKeyDown, ya sabes, función definida aquí. Entonces ha pasado mucho tiempo desde que escuchamos que se pasa, pero nunca lo afirmamos. Entonces mi pregunta sería, ¿qué tan importante es, ¿verdad? Y esto, ya sabes, puede suceder especialmente si copias y pegas muchas pruebas porque esto podría haber sido importante en otra prueba de la que copiaste esto y nunca lo eliminaste, ¿verdad? Y al repetir esto, puedes inflar tus casos de prueba uno tras otro por eso personalmente siempre escribo pruebas desde el principio. Intento, ya sabes, no copiar y pegar en absoluto porque soy perezoso. Entonces, y mi pereza me obligará a escribir la menor cantidad de código y también, ya sabes, comenzar a extraer en métodos tan pronto como repita la misma estructura por segunda o tercera vez.

6. Importancia de las Pruebas Pequeñas

Short description:

Mi pereza me obliga a escribir el código mínimo y extraer en métodos. Cualquier cambio que mantenga la prueba en verde, excepto eliminar la afirmación, es válido. Mantén las pruebas lo más pequeñas posible.

Entonces, y mi pereza me obligará a escribir la menor cantidad de código y también, ya sabes, comenzar a extraer en métodos tan pronto como, ya sabes, repita la misma estructura por segunda o tercera vez. Entonces uso mi pereza como una función forzada para pruebas más agradables, en esencia. Y también, dado que, ya sabes, supongamos que esto se escribió con el enfoque de rojo-verde-refactorizar, la prueba falló al principio. Luego implementamos algo, lo hacemos verde, ahora estamos de todos modos en la fase de refactorización. Entonces, esencialmente, cualquier cambio que podamos hacer en esta prueba que, ya sabes, la mantenga en verde, y yo espero esto, excepto tal vez eliminar la afirmación, es un cambio válido, ¿verdad? Entonces, aquí, por ejemplo, podría decir, simplemente eliminemos el onKeyDown y veamos qué sucede. Sí. Aún está en verde, y también podemos eliminar el valor inicial aquí porque eso también es, ya sabes, eso, creo que es importante, veamos. Descubramos si era importante o no. No, no parece serlo. Y solo para demostrártelo, si elimino el onChange aquí, escribo texto, pero ahora debería fallar. Sí, ahora la prueba falla. Entonces, aparentemente, ese no era un cambio que debería haber hecho. De acuerdo, con eso en mente, la lección a aprender aquí es, ya sabes, mantener las pruebas lo más pequeñas posible.

7. Los Peligros de Extraer Código en las Pruebas

Short description:

Al extraer código que está presente en múltiples pruebas, podemos acoplar inadvertidamente las pruebas e introducir un estado mutable compartido. Esto puede llevar a errores difíciles de depurar, ya que cambiar el orden de las pruebas o aislarlas puede causar fallas. Es importante evitar estos escenarios manteniendo las pruebas concisas, enfocándose en un caso de uso por prueba, utilizando afirmaciones apropiadas y priorizando el aislamiento de las pruebas sobre el código completamente seco.

Sin embargo, y esto nos lleva al último paso, hay una cosa, ya sabes, que también hice al extraer esto, es como si esta parte del código estuviera presente en múltiples pruebas, entonces, ya sabes, me adheriría al principio DRY. Sin embargo, DRY puede ser peligroso en las pruebas y déjame mostrarte por qué.

Así que veamos este último ejemplo aquí. Básicamente, estas dos pruebas, ya sabes, una verifica que la propiedad onClick no se llama cuando el botón está desactivado y la otra verifica que se llama si el botón no está desactivado, ¿verdad? Y estas pruebas se ven muy similares, ¿verdad? Sin embargo, si miramos el renderizador, entonces vemos que este pasa la propiedad desactivada, este no, ya sabes, hacer clic en el botón es exactamente el mismo código. Sin embargo, ya sabes, ya es mínimo, así que tal vez, ya sabes, no tiene sentido extraer eso. Y luego la afirmación también es ligeramente diferente porque una tiene un `not` y la otra no. Sin embargo, el método onClick que definimos aquí es, ya sabes, esta línea de código es la misma en ambos casos de prueba. Así que podrías sentirte tentado de mantener esta prueba seca, moverla fuera de la prueba, ahora mover aquí, guardar, y ya sabes, seguimos un enfoque de rojo-verde-refactorizar. Entonces, si la prueba está en verde, todo está bien y la prueba se mantiene en verde. Entonces, este cambio debe ser un cambio válido. Sin embargo, cometimos un gran error y este error es que simplemente acoplamos esas dos pruebas y las acoplamos al extraer esto, porque esto es algo que es mutable. Ahí lo tenemos de nuevo, estado mutable compartido, ya sabes la frase, es la raíz de todo mal. ¿Verdad? Entonces, en este caso, al extraer el controlador OnClick, ahora esencialmente acoplamos ambas pruebas a él y peor aún, el orden de las pruebas de repente es importante porque si muevo esta prueba debajo de esta y veamos qué sucede, comienza a fallar. Sin embargo, no falla porque el código no funciona. Simplemente comienza a fallar porque este controlador OnClick aquí comienza a contar y se ha llamado cuando se ejecuta la primera prueba, almacena esto y luego si se ejecuta la segunda prueba, esta afirmación ya no es verdadera. Porque se ha llamado en esta prueba. Entonces acoplamos nuestras pruebas y ya no están aisladas y estos errores son realmente, realmente difíciles de depurar porque si comienzo, si aíslo esta prueba, volverá a funcionar. Y esto es una de las cosas más frustrantes que hago. Si veo un fallo en la prueba, pongo un `only` en algún lugar y luego la prueba comienza a funcionar y digo, maldición. Porque entonces tengo que realmente adentrarme en el código y averiguar, ok, ¿qué está pasando? Como, ¿dónde está el estado compartido? ¿Dónde, cómo puedo hacer que no sea compartido y separar esto?

Entonces mi sugerencia general es tratar de, cierta humedad de las pruebas, creo, es buena. Solo para evitar este tipo de escenarios aquí. Y esto casi concluye mi charla. Así que solo para recapitular, ¿cuáles son los cuatro puntos importantes para aprender aquí? El primer punto es, ya sabes, tratar de adherirse a un caso de uso por prueba. Esto es realmente importante. Un caso de uso no significa una afirmación, solo, ya sabes, un caso de uso. Luego trata de usar afirmaciones que coincidan realmente con lo que quieres expresar, ¿verdad? Para que si ocurre un error, el mensaje de error proporcione la mayor cantidad de contexto posible para el aspecto particular que estás probando. Luego, cuando escribas tus pruebas, tal vez no copies y pegues demasiado, ¿verdad? Mantén las pruebas concisas y limítalas solo a lo que realmente necesitan, ya sabes, para realizar su trabajo, ¿verdad? Esto te ayuda si, ya sabes, si necesitas adentrarte en el código de la prueba para no distraerte con todo lo demás que está allí y que no hace nada, ¿verdad? Lo último es, ya sabes, no trates de ser demasiado seco con tus pruebas, ya sabes, porque el aislamiento de las pruebas es más importante que, ya sabes, el código completamente seco. Cada prueba debe funcionar por sí misma y no debe depender de algo compartido globalmente porque eso simplemente, ya sabes, conlleva muchos peligros y errores difíciles de depurar. Eso es todo.

QnA

Resultados de la Encuesta y Excepciones en las Pruebas de IU

Short description:

Gracias por escuchar. Vamos a discutir los resultados de la encuesta. Las personas que utilizan TDD la mayor parte del tiempo estaban ganando, pero algunos tuvieron problemas. Preguntas de la audiencia: Mark pregunta sobre excepciones para no usar la palabra clave 'end' en las pruebas de IU. Philip responde que depende de la situación y menciona la importancia de la testabilidad en la aplicación.

Muchas gracias por escuchar y nos vemos en el control de calidad. Adiós.

Hola, Filip. ¿Cómo estás? Gracias por la excelente charla. Muchas gracias. Disfruté mucho dando o grabando la charla. Genial. Genial.

Creo que primero podríamos analizar los resultados de la pregunta de la encuesta que presentaste en la mesa. Y en realidad, cuando estaba votando, pensé que faltaba una respuesta, que sería algo como: Me gusta hacer TDD, pero no lo hago la mayor parte del tiempo. Así que creo que esa fue la respuesta que faltaba, pero ¿qué opinas de los resultados? Me impresionó que al principio, las personas que lo usaban la mayor parte del tiempo estaban ganando, pero ahora hay algunas personas que lo intentaron y tuvieron problemas. Entonces, ¿qué piensas al respecto? Todavía me impresiona que usarlo la mayor parte del tiempo sea la segunda opción en la encuesta. A mí también. Realmente no me lo esperaba, aunque sí esperaba que algunos tuvieran problemas porque esa suele ser la respuesta que obtengo cuando pregunto a las personas si trabajan con TDD o no. Sí, pero parece una buena señal, ¿verdad? Absolutamente. Pero tal vez en el TestJS Summit, las personas estén un poco sesgadas. Es cierto. Eso es un buen punto.

Tenemos algunas preguntas de la audiencia. Así que voy a presentar la primera, que es de Mark sobre no usar la palabra clave 'end'. ¿Qué hay de los escenarios impulsados por tareas? Aquí está, él está hablando de las pruebas de IU cuando la configuración lleva una cantidad considerable de tiempo. Intentamos dividir los escenarios, pero terminamos con pruebas que tardan mucho en ejecutarse. Entonces, ¿hay excepciones a la prohibición de 'end'? Solo quería dar mi comentario antes de que respondas, que para mí, parece que hay algunos malos olores en el código de pruebas cuando no hay capacidad de prueba en la aplicación que te permita crear el estado de una manera más fácil. Cuando hablas de pruebas de IU y dependes de la IU para hacer todo. Pero me encantaría escuchar tu respuesta al respecto. Sí. Al final, también diría que depende, obviamente. Ninguna de mis reglas dice que solo se puede hacer de esta manera. Y si lo haces de manera diferente, entonces lo estás haciendo mal, por supuesto. Pero entiendo tu punto de vista muy bien.

Test Isolation and TDD Usage

Short description:

Si tu sistema actual no te permite aislar casos de uso individuales, enfócate en convertirlo en un sistema que pueda hacerlo. Tener cualquier prueba es mejor que no tener ninguna. Utiliza TDD siempre, incluso para características pequeñas, ya que te ayuda a comprender el código y asegura que estás en el lado seguro. La definición de constantes inmutables comunes en el bloque de descripción depende de la situación. Extrae las constantes si se utilizan en múltiples pruebas, de lo contrario, mantenlas en línea con la prueba. Cuando el código es completamente desconocido, realiza una prueba de experimentación para comprenderlo antes de comenzar de nuevo.

Entonces, también te preguntaría, si tu sistema actual no te permite aislar casos de uso individuales, tal vez ese sea el problema en el que deberías enfocarte y tratar de convertirlo en un sistema que realmente pueda permitirte hacer esto. Porque al final, sigues teniendo los mismos problemas, ¿verdad? Si mezclas muchas cosas, está bien, puedes tener una prueba que se ejecute rápidamente, pero luego no te brinda tanto si falla. Pero nuevamente, si estas son todas las opciones, considera que es la mejor manera de hacerlo. Y, por supuesto, hazlo, ¿verdad? Porque es mejor que hacerlo manualmente, y cualquier prueba es mejor que no tener ninguna, según mi opinión.

Exactamente, sí. Pero sí, creo que planteaste un buen punto. No siempre tenemos que culpar a las pruebas. A veces falta la capacidad de prueba en la aplicación para permitirnos escribir pruebas más aisladas y más rápidas de ejecutar. Eso es genial.

Tenemos una pregunta de Elias. ¿Crees que siempre deberíamos usar TDD o solo para algunas características? Esa es una buena pregunta. Personalmente, siempre lo haría. Porque mi regla general es que si es una característica muy pequeña y sé exactamente lo que se supone que debe hacer, entonces no necesito hacer TDD, a lo que respondería. Y si es muy pequeña y muy fácil, entonces escribir una prueba para eso tampoco lleva mucho tiempo. Así que, ya sabes, simplemente hazlo. Y de todos modos estarás en el lado seguro. Si es más grande y al escribir la prueba te das cuenta de que aún necesitas entender partes de ella. Nuevamente, la prueba, al escribir la prueba de antemano, simplemente te ha ayudado a comprender que te falta información o que necesitas prototipar un poco más para averiguar qué quieres lograr realmente. Así que siempre lo hago porque creo que siempre te ayuda mucho. Sí, eso es una buena perspectiva sin duda.

Tenemos una pregunta de Chris Christiana. ¿Crees que es una mala práctica definir constantes inmutables comunes, como el texto de los botones, en el bloque de descripción? ¿Qué opinas al respecto? Personalmente, una vez más, depende. Si es un texto común, una configuración común, por ejemplo, como una configuración predeterminada, si tiene un buen nombre, por ejemplo, uso prefijos como 'default' u otra cosa para dejar claro que esto es algo que nunca cambia y que solo necesito, entonces creo que está totalmente bien. Sin embargo, si comienzas a extraer constantes en las descripciones y solo se utilizan en una o dos pruebas y las demás no las necesitan, entonces, ¿por qué están fuera? Podría estar complicando demasiado las cosas. Mi regla general es que me gusta volver a probar de principio a fin y entender eso. Si llego a un punto en el que soy un compilador y es como, bueno, aquí está la línea, la variable, ¿dónde está esta variable? Y luego tengo que buscar en el árbol para averiguar qué hay en esta cosa ahora, entonces prefiero tenerlo en línea con la prueba y todo está bien. Sí, exactamente. Veamos, otra pregunta aquí. ¿Cómo sabes dónde poner la prueba cuando el código es completamente desconocido? Esa también es una buena pregunta. Lo que hago es que si el código es completamente desconocido, simplemente lo pruebo. Hago un experimento para averiguar con qué estoy lidiando. Y una vez que entiendo suficiente el código, simplemente descarto todo eso y vuelvo a comenzar con la prueba.

Benefits of TDD and Testable Automation

Short description:

Descarta lo que acabas de hacer y vuelve a la seguridad con TDD. El trabajo de automatización debe ser probado, así que define los criterios de aceptación de antemano. Refactoriza los scripts para tener un ejecutor de pruebas con el que te sientas cómodo. Define casos de prueba por escenarios para pruebas de extremo a extremo.

Y lo que sucede es que el 90% del tiempo termino con una solución mejor que el prototipo que acabo de escribir. Así que sí, la parte importante realmente es descartar todo lo que acabas de hacer, y luego volver a la seguridad con TDD. Eso tiene total sentido.

Tenemos otra pregunta de Elias, ¿crees que solo el equipo de desarrollo debería hacer TDD o también debería hacerlo el equipo de QA de automatización? Yo, como QA, también hago TDD. Así que quiero decir, cuando estoy escribiendo una prueba, a veces la escribo de tal manera que a veces necesitaré una función externa que haga algo por mí. Escribo el nombre de la función. Y después la implemento. Así que podría decir que esto es algo similar a hacer TDD. ¿Qué opinas?

Absolutamente. Y quiero decir, siempre y cuando el trabajo de automatización sea probado, ¿por qué no definir tus criterios de aceptación de antemano? Creo que he refactorizado un montón de scripts de S-H a, no sé, JavaScript o TypeScript o Python o lo que sea, solo para tener un ejecutor de pruebas con el que me sienta cómodo, y puedo hacer exactamente lo mismo, tal vez un poco más lento, pero luego puedo definir mis casos de prueba por escenarios. Y es como, vale, esto se carga en el bucket correcto de AWS, por ejemplo, y esta cosa, ya sabes, crea el archivo de configuración correcto o lo lee de algún lugar. Y esto, ya sabes, en todo el proceso de extremo a extremo, ya sabes, donde puedas editar la prueba, edita la prueba, porque te va a salvar en algún momento. Eso es completamente cierto.

Setting up Engineering Workflow and Mocking

Short description:

Andrew pidió consejos sobre cómo establecer un flujo de trabajo de ingeniería completo para el éxito. Philipp recomendó impartir un curso de pruebas en JS al equipo y utilizar una herramienta para la cobertura de pruebas. Hizo hincapié en comenzar con un porcentaje de cobertura bajo y aumentarlo gradualmente mientras se aprende a escribir pruebas mejores. Philipp también habló sobre la importancia de simular solo las partes más pequeñas del sistema y no simularlo todo. Sugirió utilizar el estado de la aplicación y evitar la simulación excesiva. Philipp concluyó agradeciendo a la audiencia y expresando su satisfacción por ser parte de la charla.

Hay otra pregunta aquí que me resulta interesante de Andrew, estoy liderando nuestra empresa para comenzar a escribir pruebas. No han hecho ninguna antes. ¿Algún consejo para establecer un flujo de trabajo de ingeniería completo para el éxito? Es un tema difícil. Curiosamente, he estado en una situación muy similar, creo. Lo que me ayudó fue, en primer lugar, impartir el curso de pruebas en JS de Kent Beck y no de Kent Beck, Kent C.Dodds, todos esos Kents, al equipo. Cuando se trataba de pruebas y también de cobertura de pruebas y cosas así, lo que me gusta hacer es utilizar una herramienta llamada, olvidé el nombre de la herramienta, pero básicamente obtienes una cobertura completa en el repositorio, y luego cada PR debe tener una cobertura de parche. Por lo tanto, la cobertura del intercambio de leones, que es al menos la cobertura del repositorio. Comienzas con un número muy bajo, no sé, 4%. Todos pueden lograr escribir una prueba que cubra al menos el 4% de los leones. Y a medida que avanzas, aumentas ese número, ¿verdad? Pero a medida que aumentas ese número, también aprendes a escribir pruebas mejores y mejores. Así que, esto es un ejercicio muy gratificante para el equipo. Y no dices simplemente, ok, 80% de cobertura de pruebas en todos los archivos ahora de ayer a hoy. Sí, creo que ese es un gran consejo. Hay uno aquí del que estoy muy curioso sobre tu opinión. ¿Cuál es tu opinión sobre la simulación? Ah, sí. Tan poco como sea necesario, tanto como sea posible, tanto como sea necesario, diría yo. Personalmente, trato de simular solo las partes realmente, realmente más pequeñas del sistema y no empezar a simularlo todo. Porque el problema es, ya sabes, tan pronto como simulas todo, ya no estás probando nada. Y especialmente cuando se trata de pruebas de integración, no necesitas simular tanto. Esto también es algo que aprendí, a veces piensas que necesitas simular mucho, pero en realidad no tienes que hacerlo, porque si tienes una aplicación React o Vue o cualquier otra, utiliza tu estado VueX, utiliza tu estado Redux y haz que todo pase por eso. Porque así es como funciona tu aplicación. Si crees que es demasiado lento, bueno, tal vez intenta hacer que tu aplicación sea más rápida, porque tus usuarios sufrirán los mismos problemas. Sí, sí. Y siempre es contextual también. Hay algunos contextos en los que es posible que dependas de una API externa, y puede tener sentido simularla. Creo que hiciste un buen trabajo explicándolo brevemente. Así que me gustaría agradecerte, Philipp, por la gran charla y por responder todas las preguntas. Gracias de nuevo por estar aquí con nosotros. Fue un placer. 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

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.
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.
TestJS Summit 2022TestJS Summit 2022
27 min
Full-Circle Testing With Cypress
Top Content
Cypress has taken the world by storm by brining an easy to use tool for end to end testing. It’s capabilities have proven to be be useful for creating stable tests for frontend applications. But end to end testing is just a small part of testing efforts. What about your API? What about your components? Well, in my talk I would like to show you how we can start with end-to-end tests, go deeper with component testing and then move up to testing our API, circ
TestJS Summit 2021TestJS Summit 2021
31 min
Test Effective Development
Top Content
Developers want to sleep tight knowing they didn't break production. Companies want to be efficient in order to meet their customer needs faster and to gain competitive advantage sooner. We ALL want to be cost effective... or shall I say... TEST EFFECTIVE!But how do we do that?Are the "unit" and "integration" terminology serves us right?Or is it time for a change? When should we use either strategy to maximize our "test effectiveness"?In this talk I'll show you a brand new way to think about cost effective testing with new strategies and new testing terms!It’s time to go DEEPER!
TestJS Summit 2023TestJS Summit 2023
21 min
Everyone Can Easily Write Tests
Let’s take a look at how Playwright can help you get your end to end tests written with tools like Codegen that generate tests on user interaction. Let’s explore UI mode for a better developer experience and then go over some tips to make sure you don’t have flakey tests. Then let’s talk about how to get your tests up and running on CI, debugging on CI and scaling using shards.

Workshops on related topic

React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
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
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 Summit 2022React Summit 2022
117 min
Detox 101: How to write stable end-to-end tests for your React Native application
Top Content
WorkshopFree
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and used by React Native itself as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites- iOS/Android: MacOS Catalina or newer- Android only: Linux- Install before the workshop
TestJS Summit 2023TestJS Summit 2023
48 min
API Testing with Postman Workshop
Top Content
WorkshopFree
In the ever-evolving landscape of software development, ensuring the reliability and functionality of APIs has become paramount. "API Testing with Postman" is a comprehensive workshop designed to equip participants with the knowledge and skills needed to excel in API testing using Postman, a powerful tool widely adopted by professionals in the field. This workshop delves into the fundamentals of API testing, progresses to advanced testing techniques, and explores automation, performance testing, and multi-protocol support, providing attendees with a holistic understanding of API testing with Postman.
1. Welcome to Postman- Explaining the Postman User Interface (UI)2. Workspace and Collections Collaboration- Understanding Workspaces and their role in collaboration- Exploring the concept of Collections for organizing and executing API requests3. Introduction to API Testing- Covering the basics of API testing and its significance4. Variable Management- Managing environment, global, and collection variables- Utilizing scripting snippets for dynamic data5. Building Testing Workflows- Creating effective testing workflows for comprehensive testing- Utilizing the Collection Runner for test execution- Introduction to Postbot for automated testing6. Advanced Testing- Contract Testing for ensuring API contracts- Using Mock Servers for effective testing- Maximizing productivity with Collection/Workspace templates- Integration Testing and Regression Testing strategies7. Automation with Postman- Leveraging the Postman CLI for automation- Scheduled Runs for regular testing- Integrating Postman into CI/CD pipelines8. Performance Testing- Demonstrating performance testing capabilities (showing the desktop client)- Synchronizing tests with VS Code for streamlined development9. Exploring Advanced Features - Working with Multiple Protocols: GraphQL, gRPC, and more
Join us for this workshop to unlock the full potential of Postman for API testing, streamline your testing processes, and enhance the quality and reliability of your software. Whether you're a beginner or an experienced tester, this workshop will equip you with the skills needed to excel in API testing with Postman.
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
WorkshopFree
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.