
Front end vs back end
Como programador más centrado generalmente en el back-end que en el front-end, siempre he considerado que la parte realmente importante para testear es el back-end. Con el paso del tiempo he cambiado bastante este punto de vista, aunque es verdad que la lógica de negocio debería estar toda en el back-end, no deberíamos permitir que la calidad del front end sea menor por una especia de superioridad jerárquica. Si bien es cierto que los tests en front son un poco más intrincados por la propia naturaleza de programar “pantallas”.
Al igual que pasa con un aplicativo Java, .Net o Python, la estructura y arquitectura que montemos es fundamental para poder realizar tests de calidad y que además no conlleven un consumo de tiempo totalmente inasumible.
El primer punto a tener en cuenta a la hora de lanzarse a hacer tests es saber si contamos con un framework que nos facilite esta labor. Si estamos trabajando con una herramienta como Angular, React o Vue no tienes muchos argumentos para escaquearte de programar tus tests, eso sí, debes ser muy estricto con tu arquitectura desde el minuto 0.
Otro aspecto interesante es que el diseño UX/UI esté pensado para facilitar una arquitectura de componentes reutilizable y una estructura jerárquica, por ejemplo con el uso de atomic design. Puedes leer algo sobre atomic design en este artículo. Y si te interesa el diseño web no te pierdas nuestro post sobre 10 principios básicos de diseño.
¿Por qué hacer tests en front?
Vale, tenemos las herramientas necesarias para poder hacer tests, pero ¿Por qué deberíamos hacerlos?
Al igual que pasa con los tests en back-end, sobre todo para dormir tranquilos. Si introducimos en nuestro ciclo diario de trabajo la compilación y ejecución de tests sabemos que según vamos avanzando no rompemos nada y además que cada pieza hace lo que se espera de ella.
Como estamos hablando de front, las pruebas manuales seguirán teniendo una importancia crucial, porque seguramente no vamos a detectar que una pantalla no se ve del todo bien a través de un test automatizado, pero sí podemos saber si se visualiza un literal de texto en función de una condición, o si una transformación hecha con rxJS es correcta.
Estrategia de tests
Uno de los primeros pasos es decidir qué se va a testear. Podemos realizar las pruebas a nivel de componente unitario (moléculas) o a nivel de componentes de integración (Organismos). Es importante establecer al inicio del proyecto cual será la estrategia y como vamos a medir la cobertura.
En caso de optar por una estrategia de componente unitario es muy importante que los componentes sean pequeños y autocontenidos, habiendo por su lado otros componentes que funcionan como integradores. En caso de optar por una estrategia de test de componentes de integración es importante que los componentes no sean demasiado grandes y plantear muy bien como y donde realizar cada test con el objetivo de no duplicar los mismo tests en muchos componentes.
Desde nuestro punto de vista es preferible optar por una estrategia de tests unitarios y de componente a componente. Esta estrategia permite una cobertura mucho mayor sin necesidad de repetir tests, pero exige una mayor modularización y ser muy estrictos con las buenas prácticas.
Estrategia de desarrollo
Como hablamos antes, el objetivo de los tests no difiere demasiado entre back-end y front-end: Asegurar robustez de la aplicación, asegurar la flexibilidad de la aplicación, salvaguarda ante cambios, etc. Por tanto la estrategia general de desarrollo en lo referente a componentización y testeado tampoco difiere tanto. Por ello, debemos prestar atención a ciertos puntos:
Componentes con poca funcionalidad:
Si la funcionalidad es compleja, probablemente debamos tener componentes que integran componentes sencillos
Separación de capas:
La lógica que necesite el componente llevarlo a un fichero aparte
Que cada componente solo haga una cosa y de su nivel de abstracción
Cada pieza de código debe conocer solo lo que necesita. Por ejemplo un componente web no debería saber nada del API. Para eso tendríamos que tener servicios internos del front.
Si respetamos estos principios al 100% será fácil poder realizar tests unitarios.
Mocks de componentes hijo
Si seguimos los principios indicados inicialmente y queremos tener una buena cobertura de código, entonces llegaremos a un punto que suele suponer un dolo de cabeza: Componentes de integración.
Desde la semana 1 del proyecto ya tendremos componentes que agregan proyectos y estos debemos testearlos también, ya que por ejemplo un componente puede renderizar a su ve un componente u otro en función de un dato de entrada. En estos casos es importante que nuestras pruebas comprueben que se está mostrando el componente que tiene que mostrar pero que NO pruebe el componente hijo. De lo contrario nos encontraremos con multitud de problemas. Por ejemplo: Si hay un cambio en el componente hijo empiezan a fallar tests en otros componentes.
Para solventar estos problemas podemos crear mocks de los componentes con html simple y simplemente comprobar que se pinta el componente que esperamos, aunque en el caso real este visualice lo que tenga que visualizar con la funcionalidad que necesite.
Este punto en función del framework que usemos puede ser más sencillo o más complejo.
El siguiente punto, y donde realmente se empieza a complicar el asunto, es cuando nuestro componente tiene que reaccionar a acciones del componente hijo. Sin embargo este caso también se soluciona con mocks que contienen una única acción prefijada. Si bien es cierto que cualquier cambio en la comunicación entre ambos componentes requiere cambios en las pruebas en ambos; punto por otro lado lógico porque si cambia su comunicación cambia el comportamiento en ambos lados.
Conclusión
Si planteas una aplicación front bien modularizada, con componentes suficientemente pequeños, donde no mezclas niveles de abstracción ni capas de responsabilidad, por supuesto que es viable, recomendable y óptimo hacer tets unitarios.
Como bola extra, si tu arquitectura es buena, la ayuda que puedes tener con herramientas de IA como copilot hacen que los tests unitarios se desarrollen a una velocidad muy alta sin necesidad de aumentar realmente el coste del proyecto.
En los proyectos que yo lidero no hay excusa para no tener una buena cobertura tanto en front como back, espero que si todavía no lo haces no dudes en intentarlo.
¿Te interesan más temas como este? Aquí te dejamos una lista de entradas que pueden interesarte: