Testing unitario de calidad

Test unitario calidad

El testing unitario es uno de los pilares del Software de calidad. Lleva con nosotros décadas y décadas. Está más que probado su eficacia si se hace bien… Pero, ¿cómo hacemos buenos testing unitario? En este artículo César Alberca. desarrollador front en Autentia y profesor en CICE del Máster de Desarrollo Web Fullstack, nos da una serie de consejos acerca de cómo plantear una estructura de tests unitarios robusta y completa a la vez que efectiva. ¡Comencemos!

F.I.R.S.T

Para mí lo primero es F.I.R.S.T, que son una serie de 5 principios a la hora de hacer nuestros testing unitario y son los siguientes:

  • Fast: Deben de ser rápidos. Y cuando decimos rápidos, queremos decir muy rápidos. Un test que tarda más de medio segundo ya me empieza a parecer a un test de integración. Por supuesto tema de intervalos o timeouts siempre debemos mockearlos en nuestros tests. Y nunca deberíamos hacer esperas manuales para hacer luego comprobaciones.
  • Isolated/Independent: Nuestros tests deben ser completamente independientes, no deberíamos depender de un estado de un test anterior. Debemos asumir que el orden de ejecución de los test podría ser aleatorio.
  • Repeatable: A los programadores nos gusta el determinismo. A los programadores nos gusta el determinismo. A los programadores nos gusta el determinismo. Y por tanto en nuestros tests, dada las mismas entradas, deberían dar las mismas salidas, sea ejecutado una vez o millares de veces . Debemos mockear aquello que sea indeterminista, como por ejemplo Math.random(), llamadas a APIs, a base de datos, etc.
  • Self validating: Un test debería autovalidarse. Es decir no debe ser necesario la inspección manual para comprobar si ha sido exitoso o erróneo.
  • Thorough: Debemos comprobar todas las ramas y condicionales, los casos extremos, el control de errores, inputs inesperados y un largo etcétera. Debemos ser minuciosos. Además, si testeamos los casos “raros” quedarán documentados en el test.

Y estos principios nos valen para otro tipo de test como pueden ser los de integración o los E2E. Si que es verdad que por lo menos el que “sean rápidos” dependerá del contexto. Y siendo los test de integración más lentos que los unitarios y los E2E los más lentos de todos.

Given When Then

Una buena estructura de un test suele contar con 3 secciones -que yo personalmente separo con salto de línea-. Esta estructura es conocida por varios nombres: Given When Then o Arrange, Act, Assert. Yo suelo usar más Given When Then.

Partes que caracterizan Given When Then

  1. Preparación
  2. Ejecución
  3. Aserción

En la preparación es donde crearemos los mocks, los datos que necesitamos para el test, la creación de instancias y todo lo relacionado con la preparación misma del test. Si dicha preparación se repite en muchos test podríamos mover ese código a un beforeEach o beforeAll. Es un método del que los frameworks tipo xUnit disponen.

La ejecución será donde invoquemos al método o función que es aquello que estamos testeando. Esto se suele denominar como Subject Under Test o SUT. Normalmente la ejecución suele ser una línea siendo erróneo que en un mismo test tengamos varios SUTs, si ocurre esto deberíamos partir en dos el test.

Por último, en la aserción es donde comprobaremos los resultados. Raras veces tengo más de una aserción por test, ya que si falla el test debería meterme en el código e investigar cuál es la verdadera razón por la que ha fallado. Si mantenemos una aserción por test sabremos a golpe de vista (leyendo la descripción del test) qué es lo que está fallando.

Además, si en mi desarrollo sigo TDD, lo primero por lo que empiezo es por la aserción, luego la ejecución y por último la preparación. Me ayuda a lograr que mi testing unitario se centre en la funcionalidad y me evita acoplarme a detalles técnicos en el test. Ya que de las cosas más importante del testing es testear la funcionalidad.

testing unitarios

Object Mothers

Cuando testeamos es muy común el necesitar crear datos de prueba, estos datos podríamos crearlos in situ en cada test. Pero claro, si tenemos muchos test que hacen uso de la misma entidad se puede hacer muy repetitivo. Es más, si esa entidad cambia muchos tests podrían verse afectados, pudiéndote olvidar actualizarla en muchos sitios si usas un lenguaje de tipado débil. ¿Cómo gestionamos esto? Pues con Object Mothers. Estos Object Mothers básicamente son entidades que crean objetos. Estos objetos serán usados en nuestros tests.

Algo que me ayuda mucho a la hora de usar los Object Mothers es dar nombre a los objetos que crean. En mi caso si estuviésemos hablando de un Object Mother que crea usuarios yo le pondría un nombre de método como “Joan”, que es una usuaria de mi sistema desde hace mucho tiempo. Paga la versión pro de mi aplicación y tiene todos sus datos correctos. Y luego por ejemplo podríamos poner otro método “John” que nos devolviese a John, un usuario muy nuevo del sistema, en mitad del proceso de onboarding con ciertos datos incorrectos.

¿Para qué haríamos esto? Pues para poder representar en código estos User Persona y representar distintos estados de nuestra aplicación. Además al ponerles nombre va a ser más fácil acordarnos de que disponemos de distintos sets de datos que representan cosas distintas. Y bueno, no tienen por qué ser siempre usuarios. También pueden ser una miríada de elementos distinta, como tipos de cuantas bancarias, contratos, roles, etc.

Conclusiones del testing unitario

Yo todos los días refactorizo. Y refactorizo sobre seguro, es decir hasta que mis tests no están en verde no intento mejorar la estructura de mi código. De esa forma, me aseguro que no rompo la funcionalidad anterior.

Los test me dan mucha seguridad y es por eso por lo que suelo configurar un hook de Git para que antes de hacer push se pasen los test y no te deje hacer push al repositorio. Esto va muy bien si sigues Trunk Based Development ya que evitas romper los tests para los demás. Por supuesto esto a la par que un ciclo de integración continua, para probar con fiabilidad el sistema antes de cada despliegue.

El testing unitario así como el testing en general nos aporta muchos más beneficios de lo que nos cuesta. Los test no son un malgaste de tiempo, son una inversión. Y que a media, incluso a corta distancia recuperas con creces. Lo notarás en que tendrás menos bugs y los bugs que salgan, si haces un test que reproduzca dicho bug, este no volverá a ocurrir.

El hacer testing unitario es una decisión que depende exclusivamente de nosotros. ¿O acaso a una cirujana le vas a decir que te opere con un sacacorchos en vez de un bisturí? ¿No debería ser la cirujana, que lleva estudiando tantos años medicina la que tome la decisión de cómo va a hacer mejor su trabajo? Pues seamos profesionales y tomemos la decisión de hacer desarrollos con calidad y es así como aportamos mayor valor.

 

Este artículo ha sido escrito por César Alberca, apasionad del testing, las buenas prácticas y la arquitectura. Síguele en Twitter, Github o visitar su web.

No se encontró el banner

26/03/2020 | | Blogs Destacadas

Lucía Torres Álvarez

Lucía Torres Álvarez

Escribe tu comentario

Si quieres personalizar tu avatar, click aquí.
Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *
Recuerda que los comentarios deben ser revisados por un administrador.

Mándanos tu consulta

Puedes llamarnos:

Centro Maldonado

91 401 07 02

Centro Povedilla

91 435 58 43

O si lo prefieres, déjanos tus datos y nosotros te llamamos.

*Selecciona una titulación

Te llamamos sin compromiso

Puedes llamarnos al 91 401 07 02 (Centro Maldonado) o al 91 435 58 43 (Centro Povedilla).

Si lo prefieres, déjanos tus datos y nosotros te llamamos.

Solo hasta el 25 de marzo

¡MATRÍCULA

GRATIS!

Solo quedan


*Consulta condiciones aquí
Testing unitario de calidad
Buzón de quejas




Acepto las condiciones legales

SOLICITAR UNA CLASE DE PRUEBA GRATUITA
Testing unitario de calidad

Horario atención al cliente

  • Lunes a viernes

    • De 9 a 14 horas
    • De 16 a 21 horas
  • Sábados

    • De 9 a 14 horas

Teléfono de contacto: 91 435 58 43

Solicita información sobre
Envíanos tu opinión sobre CICE
Nosotros te asesoramos

¿No te decides?

Nosotros te ayudamos. Utiliza nuestro buscador avanzado para encontrar el curso que quieres.