Testear nuestro código no es más que comprobar que funciona correctamente. Lo hacemos constantemente… pero a mano. Sin embargo, como programadores deberíamos poder aprovechar la tecnología para asistirnos en esta tarea. Es aquí donde entra en juego el test automatizado.
¿Por qué queremos hacer tests automatizados?
Los tests automatizados son programas que lanzamos contra nuestro propio código para que verifiquen que todo funciona como debe. Ten en cuenta que, tanto en el proceso de desarrollo como en el de mantenimiento, podemos tocar algún fragmento de código que haga que aparezca un bug.
Cuando rompemos un trozo de código “localmente” no tenemos un gran problema, porque es fácil que encontremos el error. El problema gordo llegará cuando hayamos roto alguna funcionalidad “lejana” al lugar donde estamos trabajando.
Por ejemplo, cuando estaba empezando desarrollé un ERP modular. El módulo de usuarios fue el primero que terminamos, y todo funcionaba correctamente. Meses más tarde, tras completar el quinto o el sexto módulo, nos dimos cuenta de que el de usuarios había dejado de funcionar.
¿Cuándo lo habíamos roto? Fue el cliente quien nos avisó, así que no sabíamos muy bien hasta donde llegaban los daños. Pero, lo más escalofriante de todo era… ¿Qué más nos habíamos cargado por el camino?
Los tests automatizados nos liberan de estos peligros. Facilitan la tarea de verificación y se aseguran de comprobar que la totalidad de nuestro código sigue funcionando adecuadamente tras cada cambio que hacemos. Además, son más rápidos, precisos y minuciosos que los tests manuales.
No hace falta que pases por un escenario como el que describo para mejorar la calidad de tu código. Integrando el testing en tu flujo de trabajo, desarrollarás software más seguro, estable y de mejor calidad.
¿Qué tipos de tests existen?
Existen muchos tipos de test diferentes. A lo largo de este curso nos centraremos en los tests unitarios, por ser la mejor entrada al mundo del testing. Pero también hablaremos de los tests de integración, de los test end to end (E2E) y de otros tipos de test.
Test unitario
Un test unitario trata de verificar que los bloques con los que construimos nuestra aplicación funcionan adecuadamente. Normalmente, comprobará funciones, clases, componentes… siempre bloques pequeños (de ahí su nombre: unidad).
Toda aplicación se compone de unidades de código. Por tanto, si todas las unidades de código funcionan, nuestra aplicación debería funcionar (aunque ya veremos que esto no es siempre así).
Al disponer de una batería de tests unitarios podemos lanzarlos contra el proyecto cada vez que hagamos el más mínimo cambio. De ese modo nos aseguramos de que no estamos introduciendo errores inadvertidos. Es más, podemos incluso utilizar herramientas como husky y los github webhooks para evitar subir a nuestro repo código que vaya a romper algún test preparado previamente.
Como ventaja colateral, los tests unitarios nos fuerzan a escribir un código más limpio y de mayor calidad. Y ello porque deberemos testearlo, y si nuestro código no es limpio y organizado, nos estaremos complicando la vida.
Test de integración
Los test de integración comprueban que, al unir los bloques de código, funcionen adecuadamente. Aunque una unidad sea nuestro bloque básico de construcción y ya hayamos comprobado que funciona adecuadamente, podría ocurrir que aparecieran casos límite o bugs al combinar todo nuestro código.
Aquí es donde entran en juego los test de integración, que deben ser:
- Un complemento a los tests unitarios.
- Como complemento, menos numerosos que los tests unitarios.
Test E2E
Los test end-to-end tratan de emular un flujo de uso real de la aplicación. Básicamente comprobaremos funcionalidades completas. Por tanto, deben ser todavía más minoritarios que los tests de integración, a los que sirven de complemento.
¿Qué es el Test Driven Development (TDD)?
El Test Driven Development (TDD) es una disciplina que consiste en escribir los tests antes que el código que están testeando. Como cualquier disciplina, supone comprometerse con unas normas y un flujo de trabajo:
- Primero escribiremos un test que compruebe lo más básico de nuestro código. Por ejemplo, que existe una función.
- A continuación lanzaremos los test. Obviamente, el test fallará, porque todavía no existe ninguna función.
- Ahora deberemos hacer la implementación mínima para que el test tenga éxito. Por ejemplo, escribir una función (todavía sin funcionalidad alguna).
- Superado el test, podemos aprovechar para refactorizar nuestro código o volver a iniciar el ciclo, añadiendo una nueva funcionalidad a nuestra suite de tests.
Este proceso nos fuerza a escribir un código más limpio y de mayor calidad. Además, garantiza que los tests que estamos escribiendo son útiles y describen el funcionamiento y las características clave de nuestra aplicación. Profundizaremos más en esta filosofía a lo largo del curso.
¿Qué necesitamos para hacer tests?
Lo primero que necesitamos para hacer testing es preparar un entorno de desarrollo con las herramientas necesarias. Básicamente son:
- Nuestro entorno de desarrollo habitual. A fin de cuentas, los tests solo son un complemento: están ahí para mejorar nuestro código, pero no lo sustituyen.
- Test runner. El test runner o ejecutor de tests es simplemente un software que encontrará nuestros tests, los ejecutará y mostrará los resultados de una forma legible. Ejemplos de test runners son Jest, Karma o Vitest.
- Assertion library. Una librería de aserciones lleva funciones que nos permiten expresar nuestras expectativas y comprobar si el output de nuestro código se corresponde con estas. Ejemplos de assertion libraries son Jest, Chai o Vitest.
Siguientes pasos
Antes de terminar el día, busca las herramientas que necesitas para continuar con el curso. Yo voy a utilizar vitest, así que te recomiendo que eches un vistazo a su documentación. Los pasos que tendrás que seguir para poder hacer ejercicios mientras sigues las siguientes lecciones son:
- Abre un nuevo repo.
- Instala vitest. npm install -D vitest
- Configura tu package.json para que tus scripts incluyan "test": "vitest"
- Revisa su documentación oficial.
Curso de introducción al testing
Visita mi repositorio intro-to-testing para ver ejemplos de todo lo que hemos visto a lo largo de este curso:
- ¿Qué es el testing?
- Unit testing
- Conceptos intermedios de testing
- Cómo hacer tests en el DOM