En el artículo de hoy, les voy a presentar qué son las pruebas unitarias (unit tests en inglés) y cuáles son los beneficios que pueden traer al proceso de desarrollo.

Una definición

Son pruebas automáticas, escritas por el desarrollador a medida que vaya programando.

Se llaman pruebas unitarias, porque cada prueba unitaria tiene como responsabilidad de testear el buen funcionamiento de una unidad aislada del sistema. La idea es guardar la especificación de esa unidad, pero como código fuente, para que la computadora misma pueda comprobar que esa especificación sea cumplida por el sistema.

Lo ideal, es correr las pruebas unitarias lo más frecuentemente posible, para que sirvan de guía al momento de desarrollar. Tengo las mías configuradas para que se corren automáticamente cada vez que salvo un archivo de código, es decir varias veces por minuto.

Un ejemplo

Aquí está un ejemplo de la prueba unitaria de una función que suma sus dos parámetros, llamada my_sum. Este ejemplo es en ruby, usando la librería de pruebas minitest.

def test_my_sum
  my_sum(1, 3).must_equal 4
  my_sum(5.4, 6).must_equal 11.4
  my_sum(0, 0).must_equal 0
  my_sum(-1, 0).must_equal -1
end

Si hay un defecto en la implementación de la función my_sum, esta prueba lo detectará, permitiendo al desarrollador encontrar y arreglar el defecto.

Naturalmente un método que sume sus parámetros no es muy complicado, pero si uno quiere estar seguro que no tiene error, entonces sí se necesita una prueba unitaria.

Las pruebas unitarias, quizás el tipo de pruebas más importante

Pirámide de las pruebas

Esta es la pirámide de las pruebas. Es una manera de visualizar cómo los diferentes tipos de pruebas se relacionan los unos con los otros. En este gráfico, la base son pruebas que conocen mucho del sistema. Más se sube al tope de la pirámide y más las pruebas se hacen del punto de vista de un usuario, sin tener que conocer o preocuparse con los detalles técnicos del sistema.

Las pruebas automáticas forman la base de la pirámide: es decir que son las más importantes para la estabilidad del sistema y son las más numerosas.

Las características de las pruebas unitarias

Las pruebas unitarias son el tipo de prueba que más lineas de código necesitan.

Si uno quiere tener una gran parte de su sistema testeado con pruebas unitarias, entonces es común tener la misma cantidad de líneas de código de pruebas unitarias que de de líneas de implementación. Aunque esta cifra pueda parecer aterradora, tener pruebas permite tener mucho menos líneas de implementación, gracias al proceso de refactorización.

Podemos resumir eso en la siguiente tabla:

Cantidad en Código de Implementación Relación Cantidad en Pruebas Unitarias
líneas de código ~= líneas de código
clases = clases
métodos/funciones públicas = métodos

(El símbolo ~= quiere decir más o menos igual)

Lo más frecuente en las pruebas unitarias, es tener una clase de prueba por cada clase de implementación. Y para cada método/función pública de esa clase, tener un método de prueba correspondiente.

Por el hecho que sean las pruebas más cercanas a la aplicación, es muy común que estén escritas en el mismo lenguaje de programación que el programa. Todos los lenguajes de programación un poco conocidos tienen uno o varios frameworks de pruebas.

Unos ejemplos:

  • python: pyunit
  • java: junit
  • ruby: minitest, rspec
  • javascript: jest, test double

Personas implicadas con las pruebas unitarias

Primeramente, son los programadores que más están involucrados con las pruebas unitarias. De hecho, es el programador que tiene que escribir sus propias pruebas unitarias, cada vez que agregue una nueva unidad lógica al programa (cada vez que agrega un método).

Pero no son los únicos que tienen que interactuar con las pruebas unitarias.

Otro departamento que siempre está involucrado en todas las pruebas, es el departamento de QA (Quality Analysis). La responsabilidad de ellos es escribir las pruebas de integración (automáticas), las pruebas funcionales (también automáticas) y hacer pruebas exploratorias manuales. Aunque no tengan que escribir las pruebas unitarias ellos mismos, es importante para la empresa que puedan al menos leerlas.

También es importante que los jefes del departamento de tecnología tengan un buen conocimiento de las pruebas unitarias y que entiendan sus costos y sus beneficios, para tomar las decisiones sobre qué parte del sistema testear y para hacer que los desarrolladores cumplen con esa tarea.

Es difícil escribirlas

A pesar de los numerosos beneficios de las pruebas unitarias, aprender a escribirlas es como aprender a programar de nuevo, porque se necesita tener otra mentalidad al momento de escribir las pruebas, saber estructurarles, poder tener pruebas resistentes al cambio, pruebas comprensible, etc. También es muy importante saber qué partes del sistema se tienen que probar y hasta qué punto, es decir, siempre quedarse pragmático.

También se necesita aprender la librería de pruebas, saber cómo trabajar con datos de prueba, saber abstraer/simplificar unas partes del sistema para poder escribir las pruebas (¿qué pasa si el método que quiero probar tiene que comunicarse con el Servicio de Rentas Internas?).

Como todo, es algo que necesita tiempo y experiencia, para poder aplicarlo mejor. Es muy importante pensar cómo introducirlo en tu empresa, porque si no se hace bien, las desventajas se pueden hacer más evidentes que los beneficios, más aún por el hecho de que esos beneficios se perciban más a largo plazo.

Conclusión

Escribir pruebas automáticas es seguramente el pilar más importante sobre el cual se apoyan las otras prácticas, que juntas van a permitir mejorar mucho el proceso de desarrollo y la calidad del sistema.

La base de las pruebas automáticas está formada por las pruebas unitarias, que deberían ser parte integrante del trabajo de los desarrolladores.

En un futuro post te presentaré cuáles son los beneficios, pero también cuáles son los costos que puedes esperar al escribir pruebas automatizadas.