En este artículo te quiero contar por qué las pruebas automatizadas son tan importantes, más allá de lo técnico.
Si lees libros sobre programación, hacés cursos, estudiás en la universidad o seguís a referentes del mundo del desarrollo, verás que siempre te recomendarán realizar pruebas automatizadas.
En este post, quiero ser uno más y aportar mi granito de arena a la causa. Para ello, quiero contarte mi opinión al respecto de las pruebas automatizadas mostrándote tanto lo bueno como lo malo.
Al final del artículo te voy a contar algo más personal vinculado a este tema. La verdadera razón por la que defiendo el testing automatizado.
Si bien no me quiero meter con la parte técnica de las pruebas en este artículo, es insoslayable y debemos comenzar por ahí.
Contenido
Ventajas de las pruebas unitarias desde un punto de vista técnico
Repasemos algunas de las ventajas conocidas y más claras de escribir código que prueba código.
Requieren que el código esté desacoplado
Generalmente, cuando se comienza con las pruebas unitarias, uno toma los componentes más sencillos. ¿Por qué? Porque son los más fáciles de probar.
La pregunta es, ¿por qué no se comienza con los componentes más grandes e importantes?
La respuesta suele ser porque son inmensamente más difíciles. Y esto se debe en la mayoría de los casos a que tienen demasiadas dependencias. Por lo tanto, la única forma de testear bien un componente complejo, es remover las dependencias y desacoplarlo.
Esta acción en sí mismo permite mejorar el código no sólo para probarlo, sino también para mantenerlo.
Contemplan cada uno de los posibles escenarios
Si las pruebas están bien hechas, hay menos probabilidades de que tengamos bugs en nuestros sistemas.
Yo siempre pensé este concepto como un medio mundo de esos que usan los pescadores. Cada prueba es un cuadradito más en la vasta red. Cuantos más haya, más bugs se capturan.
Es imposible cubrir absolutamente todos los casos, pero hay que intentarlo al máximo.
Son un respaldo necesario a la hora de refactorizar
Reescribir el código para mejorarlo es algo fundamental para que nuestros sistemas sean livianos, ágiles y fáciles de mantener. Pero esto no se puede hacer sin un buen respaldo de pruebas.
Se necesita una batería de tests que te asegure que no estás rompiendo nada a la hora de ir refactorizando.
Permiten escalar el código de forma más rápida y ordenada
Agregar funcionalidad es más fácil y seguro si se hace sobre una base sólida y probada.
Aquí el único desafío es mantener la constancia y seguir construyendo a base de pruebas. No hace falta que sea con un enfoque TDD, pero sí tiene que haber siempre un respaldo para cada línea de código nueva.
Vayamos ahora con lo que muchos no te dicen sobre las pruebas automatizadas.
Lo difícil de las pruebas automatizadas
Decir que hay que escribir pruebas automatizadas es una cosa y escribirlas realmente es otra (me incluyo). Sin embargo, no ocurre que somos vagos o malos profesionales. Simplemente, hay ciertas cuestiones que lo hacen difícil.
Escribir código desacoplado
Antes te contaba las virtudes del código desacoplado. Sin embargo, a veces no es tan fácil producir código con dependencias bien administradas.
Para poder cumplir con este objetivo es necesario tener algunos conocimientos técnicos como inversión de dependencia, inyección de dependencias, patrones factory y builder, entre otros.
Una buena práctica es que cada vez que se instala un paquete, se acceda a este siempre a través de una clase o un componente que funcione como Adapter, a través de composición.
Aun así, sabiendo todo esto, el código que escribimos no suele estar tan desacoplado como nos gustaría y esto es una realidad.
Aprender un framework de pruebas es tedioso
Hace unos cinco años yo trabajaba casi en exclusividad con Zend Framework 2 y PHPUnit. La tenía clarísima con la parte de las pruebas. Tenía gran parte de mis proyectos respaldados con pruebas unitarias y E2E (end-to-end).
Unos años después pasé a Laravel y me costó un poco llevarme todo ese conocimiento a un nuevo framework. Si bien seguía usando PHPUnit, las pruebas eran diferentes con Laravel.
Tiempo más tarde, aterricé en el mundo JavaScript y si bien librerías como Jest y Vitest me son familiares, la verdad es que me ha costado mucho aprender sus APIs y métodos particulares.
Cuando comencé con Node.js yo ya sabía trabajar con pruebas unitarias y con enfoque TDD, pero no tenía idea de cómo usar Jest, por lo que tuve que dejar eso para más adelante.
Aprenderse todo un framework de pruebas lleva tiempo y, lamentablemente, no es lo primero que uno suele aprender. Y está bien que así sea. Cuando uno comienza con una tecnología nueva, primero tiene que acostumbrarse a usarla y luego sí, incorporar temas más avanzados.
Mantener las pruebas
Si la funcionalidad cambia, el código tiene que cambiar y las pruebas también. Y aquí es donde muchos fracasan y tengo que admitir que a mí me cuesta mucho, especialmente cuando trabajo con una librería de pruebas que no domino.
El asunto aquí es comprender que las pruebas no son un complemento al código. Son parte del código. Por lo tanto, hay que mantenerlas de la misma forma que se mantiene cualquier funcionalidad clave del sistema.
Hay que tener en cuenta esto tanto para cuando se modifica funcionalidad como para cuando se agrega nueva.
Las pruebas te ralentizan al principio
Es innegable que cuando uno empieza a escribir pruebas desde el principio, el avance es más lento. He escuchado a gente decir que no es así, pero yo, que soy un férreo defensor de este enfoque, admito que al principio parece que la cosa no avanza.
Esto hace que te tientes a escribir código sin respaldo. Pensás: «Después vuelvo y escribo la prueba». Bueno, no. Sabemos que eso no va a suceder.
Así como es cierto que el principio es más lento, también es cierto que el código que se va construyendo es mucho más sólido. No hay que dejar de tener esto en mente. Pensalo como un sacrificio de hoy para mañana contar con un sistema fuerte y probado.
Pruebas unitarias antes y ahora
Hace 30 años un programador dominaba un único lenguaje y se sabía de memoria todas las instrucciones. Hoy en día, estamos obligados a manejar varias tecnologías y cada una viene con su repertorio y sus variaciones a la hora de aplicar determinadas técnicas.
En los 2000s, cuando estaba en la universidad, aprendí a programar con pruebas unitarias, usando Java y JUnit. Era muy feliz. Había un único lenguaje y un único framework. Nada se escapaba de eso.
Es mejor tener pocas pruebas automatizadas, que no tener ninguna.
Hoy, 20 años después, tengo que recordar la sintaxis de PHPUnit, la de Mocha, Jest, Vitest y cualquier plugin o extensión de estos. Es mucho más difícil.
El no dominar estas librerías te puede llevar a prescindir de ellas. De hecho, como te comentaba antes, esa sensación de no poder estar avanzando a la velocidad esperada te puede llegar a desesperar.
Mi consejo es que le dediques todo el tiempo que puedas a aprender estas librerías y que intentes probar todo lo que puedas. Yo sé que no vas a poder probar todo, pero en la medida de lo posible, andá probando lo que puedas. A mí me pasa todo el tiempo.
Recordá que es mejor tener pocas pruebas que no tener ninguna prueba.
Ahora sí. Te voy a contar la razón por la cual le doy tanta importancia a este tema de las pruebas.
La verdadera necesidad, dormir bien a la noche
Cuando trabajaba para una empresa de desarrollo teníamos un cliente muy grande que solía reportar bugs en los sistemas que le hacíamos. Cada bug era un dolor de cabeza y la verdad es que me hacía sentir mal.
Por ese entonces yo sabía programar escribiendo pruebas, pero no lo hacía por varios de los motivos que escribí arriba. Principalmente porque teníamos un deadline muy cercano y porque no comprendía bien la librería de pruebas que debía usar (que era PHPUnit).
Llegó un punto en que quedé casi traumado porque no tenía suficiente confianza en el código que escribía, especialmente después de cada despliegue, que era cuando llegaban los reportes de bugs más pesados.
Las pruebas automatizadas son un respaldo para asegurarte de que has hecho bien tu trabajo.
Cada mail o llamada por teléfono era un martirio para mí. Por las noches me acostaba pensando si al otro día me tendría que levantar temprano para encontrarme con otro reporte de bugs.
El proyecto fue exitoso finalmente, pero la pasé mal.
Tiempo después, ya como freelancer, tuve un cliente que trabajaba en horario de oficina y podía también reportarme bugs. Pero en esta oportunidad no quise repetir errores del pasado. Me blindé con pruebas unitarias y E2E.
Cada vez que desplegaba la app, corría las pruebas y si bien, siempre algún bug aparecía tras los despliegues, eran casos puntuales y muy menores.
Por las noches dormía tranquilo, sabiendo que nada malo podía pasar. Esa es la diferencia y ese es el motivo por el cual yo pruebo todo lo que puedo probar, especialmente cuando es para un cliente grande y exigente.
¿TDD sí o no?
Por último, hablemos del test driven development, o desarrollo guiado por pruebas. ¿Es realmente necesario?
Si no sabés lo que es TDD te cuento que consiste en ir construyendo el código generando primero pruebas. Es decir, escribís una prueba y generás un código que la cumpla. Escribís otra, y lo mismo. Y así vas construyendo tu código.
Yo soy partidario de TDD siempre que sea posible aplicarlo, pero reconozco que no tiene sentido escribir todo TDD.
El desarrollo guiado por pruebas es una gran herramienta para construir el núcleo de los modelos de los sistemas.
Personalmente, cuando hay algo de lógica de negocios, en lo que podría ser el modelo de una app, prefiero un enfoque TDD.
Si estoy construyendo un CRUD básico, difícilmente opte por un enfoque de estas características aunque sí cubriría todos los casos posibles mediante pruebas E2E.
Si estoy aprendiendo algo nuevo prefiero no añadir la dificultad de las pruebas y menos, un enfoque TDD.
A veces es cuestión de gustos personales. Sin embargo, en mi experiencia, el código producido con TDD es superior en calidad al no producido con esta técnica.
Más contenido sobre programación en Crónicas Freelancer
Espero que este artículo te haya gustado. Si tenés alguna duda o querés hacer algún aporte, dejame un comentario.
Si estás buscando hosting, te recomiendo Digital Ocean. Seguí este enlace para obtener US$ 200 de crédito para usar en un periodo de 60 días.
Te invito a que me sigas en las redes: LinkedIn, X, GitHub e Instagram. También estoy en CodeWars, plataforma que te recomiendo para practicar ejercicios de programación.
También te podés suscribir a la lista de correo de este blog para recibir las novedades en tu correo electrónico.
Eso es todo. Muchas gracias por tomarte el tiempo de leerme.
Hasta la próxima.