Tipos de pruebas automatizadas

Los nombres que se asignan a los diferentes tipos de pruebas suelen tener temas en común en todas las bases de código, pero no tienen definiciones particularmente rigurosas. En este curso, se proporcionan algunos lineamientos sobre el significado de cada tipo de prueba, pero otros recursos podrían proporcionar definiciones diferentes.

En las páginas anteriores, hubo ejemplos de pruebas de unidades y pruebas de componentes (en nuestro ejemplo, se hace referencia a un componente de React). Podemos colocar ambos en una parte baja de nuestra pirámide de pruebas (o en otra forma), ya que tienen una complejidad baja y se pueden ejecutar rápidamente, pero es posible que no tengan tanta utilidad como una prueba de integración más compleja.

Algunos ejemplos de pruebas de formas de estrategias: una pirámide, un diamante cortado, un cono de helado, un hexágono y un trofeo.
La estrategia de prueba tiene diferentes formas.

Tipos comunes de pruebas

Pruebas de unidades

Las pruebas de unidades tienen el menor alcance. Suelen usarse para probar pequeñas partes del código, o código sin estado, de manera casi matemática: si proporciono tu código con las entradas X, Y y Z, el resultado debería ser A, B y C.

El código con pruebas de unidades normalmente no tendrá dependencias externas, como la recuperación desde una red o el uso implícita de otras funciones o bibliotecas. Es un nodo de árbol de tu código que puedes "cortar" y probar por su cuenta.

Si bien las pruebas de unidades suelen ser rápidas de escribir y ejecutarse, siempre es posible que las pruebas de unidades de código pequeñas no proporcionen información útil. A menudo, la falta de interacción de una unidad de código con otro código significa que es mejor realizar pruebas en un nivel superior para reducir el riesgo.

Pruebas de componentes

Para los desarrolladores web, el nombre "componente" está sobrecargado, lo que a menudo significa un componente visible para el usuario, como un componente de React o un componente web. Su definición más general es un fragmento de trabajo que se puede probar, por ejemplo, una clase con dependencias externas. Para que se pruebe de manera efectiva, este componente debe omitirse o simular sus dependencias.

Debido a que las prácticas modernas de desarrollo web se basan en el concepto de un componente, las pruebas de componentes son una forma práctica de pensar en las pruebas: por ejemplo, puedes decidir que cada componente necesita una prueba. Las pruebas de componentes también son fáciles de realizar en contextos en los que un solo desarrollador o un equipo pequeño afirman que son propietarios claros sobre un componente. Sin embargo, puede ser difícil simular dependencias complejas.

Pruebas de integración

Por lo general, se prueba una pequeña agrupación de componentes, módulos, subsistemas u otras partes significativas de tu código para garantizar que funcionen correctamente. Es una definición muy imprecisa. Si eres desarrollador web, imagina que el código que estás probando no es la compilación de producción real de tu sitio (ni siquiera cerca), pero de todos modos conecta varios componentes relacionados de tu sistema.

Esto incluso puede incluir dependencias "reales", como una base de datos externa en modo de prueba, en lugar de una pura simulación. Por ejemplo, en lugar de decir que query() siempre mostrará las mismas dos entradas, la prueba de integración puede confirmar que una base de datos de prueba tiene algo en ella. Los datos en sí son menos importantes, pero ahora probarás que se pueda conectar una base de datos y que se pueda consultar correctamente.

Es posible escribir pruebas de integración relativamente simples con implicaciones de amplio rango que se pueden verificar mediante aserciones, ya que una sola acción conectada a varios componentes puede causar una serie de efectos medibles. Debido a esto, las pruebas de integración pueden demostrar de manera eficaz que tu sistema complejo se ejecutará según lo previsto. Sin embargo, pueden ser difíciles de escribir y mantener y pueden introducir una complejidad innecesaria. Por ejemplo, escribir un FakeUserService para una prueba de integración agrega el requisito de que tanto esta como RealUserService tengan que implementar un UserService.

Pruebas de humo

Estas son pruebas que deben completarse muy rápido y determinar si la base de código se encuentra en un estado razonable. En la práctica, esto significa, en gran medida, realizar pruebas simples en el código que tiene efectos muy variados en tu experiencia.

Por ejemplo, en una app web con acceso de gran tamaño, esto podría garantizar que el sistema de acceso y autenticación funcione, ya que sin él la app no se puede usar y las pruebas adicionales son irrelevantes.

Las pruebas de humo pueden ser una buena opción para ejecutarlas bajo la secuencia de comandos test de tu package.json en una base de código grande. Las pruebas manuales también pueden actuar como una especie de prueba de humo.

Pruebas de regresión

Las pruebas de regresión son un tipo de prueba de humo que garantiza que las funciones existentes sigan funcionando o que no se vuelvan a introducir errores anteriores después de una versión nueva o el desarrollo de otra función.

Esto se relaciona con el concepto de desarrollo basado en pruebas (TDD). Los casos de prueba escritos para activar explícitamente un error y que luego se usan para garantizar que se corrija el error cuentan como casos de prueba de regresión, ya que su existencia debería impedir que se muestre el mismo error.

Sin embargo, las pruebas de regresión pueden ser un problema sin una gran solución. Es un término que suelen mencionarse las necesidades empresariales: a medida que se desarrollan los atributos, es importante que los anteriores no se rompan. Una base de código bien probada debería poder mantener esto, pero las bases de código reales no siempre están a la altura de lo ideal. Se tratará más en las próximas secciones.

Pruebas visuales

Las pruebas visuales implican tomar capturas de pantalla o videos del estado de un sitio web para comparar un estado óptimo conocido (como una captura de pantalla anterior) con la ejecución de prueba actual. Por naturaleza, requiere que se ejecute un navegador real para que pueda renderizar código HTML, CSS y otras partes del sitio web.

En lugar de probar visualmente las pruebas de extremo a extremo que ejecutan toda la base de código, puede ser útil crear "arneses" de HTML que rendericen solo ciertos componentes, en especial en diferentes tamaños de pantalla, para activar IU responsivas. Esto es más complejo que solo usar JSDOM o frameworks similares.

Si fallan las pruebas visuales, puede ser una buena señal de otros tipos de fallas. Sin embargo, las IU complejas pueden fallar las pruebas visuales por motivos no relacionados con las funciones que intentas probar, como otras funciones nuevas que cambian la apariencia de la IU o incluso un emoji nuevo de renderización de la versión del SO diferente de las versiones anteriores.

Pruebas de extremo a extremo

Las pruebas de extremo a extremo suelen estar en la parte superior de la pirámide de pruebas. Describen una interacción de experiencia completa con tu app web o sitio web, quizás centrada en una función específica y, por lo general, se ejecutan dentro de un navegador controlado por un agente como WebdriverIO, Selenium o Puppeteer, que puede ejecutar tu base de código de la misma forma en que se implementaría en producción (aunque a menudo se entregan en localhost).

Según tu sitio, esto puede implicar que accedas como usuario de prueba, realizar acciones importantes y confirmar que tu sitio o sistema esté en el estado correcto. Analizaremos más ejemplos de este tipo de pruebas en secciones adicionales, ya que pueden ser muy potentes, pero a veces difíciles de mantener.

Algunas tácticas para simplificarlas pueden incluir reducir su alcance o simular componentes específicos cuando sea relevante. Por ejemplo, si los usuarios necesitan acceder a tu sitio, pero acceder no es la función que estás probando, te recomendamos establecer una marca para los entornos de pruebas que permita que el controlador de pruebas actúe como un usuario sin acceder ni crear las cookies asociadas.

Aunque las pruebas de extremo a extremo pueden ser maneras muy potentes de realizar pruebas en grandes secciones de la base de código al mismo tiempo, estas pruebas a gran escala corren el riesgo de ser inestables o poco confiables debido a su dependencia de sistemas externos. A menudo, también pueden dejar muchos datos de prueba en tu base de datos si, por ejemplo, cada prueba crea o modifica una entrada. Acumular datos restantes como este puede dificultar la determinación de cómo falló una prueba.

Pruebas de la API

Las pruebas de API pueden hacer referencia a confirmar el comportamiento de las APIs que proporciona tu software o acceder a las APIs del mundo real (posiblemente activas) para confirmar su comportamiento. De cualquier manera, esto tiende a probar las abstracciones entre sistemas (cómo se comunicarán finalmente entre sí) sin integrarlas en realidad como en una prueba de integración.

Estas pruebas pueden proporcionar un precursor básico de las pruebas de integración sin la sobrecarga de ejecutar los sistemas entre los que pruebas las conexiones. Sin embargo, las pruebas de los sistemas del mundo real pueden ser inestables.

Otros tipos

Existen otros enfoques para realizar pruebas que podrían ser útiles, según la fuente. Algunos ejemplos interesantes son los siguientes:

  • Pruebas manuales.
  • Las pruebas de aceptación, un tipo de prueba manual popularizada por Agile, confirma que el producto "satisface las necesidades del usuario".
  • Las pruebas de caos son ingresar datos aleatorios para ver qué sucede a fin de garantizar que un sitio no falle si se ingresan datos incorrectos.
  • Las pruebas de fallas simulan fallas de forma intencional en sistemas complejos, como fallas de red, para garantizar que el código que se está probando responda de forma controlada.
  • Las pruebas de compilación confirman que se pueden generar los artefactos de compilación de una base de código mediante la verificación de su existencia o de cuál es su contenido. Este tipo de prueba puede ser útil para verificar el resultado de un CMS complejo.

Cobertura de código

Es posible medir qué porcentaje del código se prueba con las pruebas automatizadas y, luego, informarlo como una estadística a lo largo del tiempo. No recomendamos que tengas como objetivo una cobertura del 100% del código, ya que puede generar una sobrecarga innecesaria, así como pruebas sencillas o mal diseñadas que no abarcan los casos de uso en profundidad.

La cobertura en sí misma también puede ser una herramienta útil a la hora de escribir o trabajar en tus pruebas, especialmente las de integración. Cuando se muestra un porcentaje o un desglose línea por línea del código que se prueba en una sola prueba, puedes obtener información valiosa sobre lo que falta o lo que se puede probar a continuación.

Recursos

Verifica tus conocimientos

¿Cuáles de las siguientes opciones son tipos conocidos de pruebas?

Pruebas visuales
Pruebas de caos
Pruebas de incendios
Tal vez si estás creando software para un departamento de bomberos.
Pruebas de diferenciación
Pruebas de esfuerzo
No mencionamos esto aquí, pero las pruebas de esfuerzo o carga son un tipo de prueba de los sistemas de producción para garantizar que puedan aceptar una gran cantidad de tráfico. Está más asociado con el diseño de sistemas grandes que con la prueba de bases de código más comunes.