Introducción a pruebas unitarias en Ruby

Manuel Rodrigues
Academia Hack
Published in
5 min readJun 11, 2019

En este artículo encontrarás la importancia de las pruebas unitarias, comenzaremos por una breve introducción y veras algunos flujos de trabajo en donde aplicarlas.

Pruebas unitarias, tan esencial para los Seniors y tan infravalorada por los Juniors.

Pongamos un hipotético caso en el que trabajarás en un proyecto en Ruby ya empezado por otros desarrolladores con los que nunca has trabajado ni tienes referencias de ellos. Imagina que necesitas tener un status del proyecto lo antes posible, y necesitas revisar el código para dar un presupuesto. Teniendo en cuenta que Ruby es un lenguaje interpretado, ¿Como podrías saber si no existen errores de sintaxis en el proyecto?, ¿Tienes que revisar cada linea de código del proyecto para verificar que todo está bien?, ¿Como podrías saber si en algún lugar un método podría recibir parámetros erróneos?, y peor aún ¿Como podrías saber si el código se apega a los requerimientos del cliente?.

Photo by Artem Sapegin on Unsplash

Es posible que hacer esa revisión por tu cuenta te lleve más tiempo de lo que piensas y al no tener la ayuda de un compilador que nos indique los errores en el código, se empezó a buscar solución a este problema. Y es en este punto donde las pruebas unitarias empiezan a tener un gran valor.

Las pruebas unitarias no son mas que bloques de código creados para verificar si el método a probar funciona de la manera correcta. Estas pruebas son creadas con la única finalidad de probar la funcionalidad de sólo un método, es decir, deberían existir, mínimo, la misma cantidad de pruebas unitarias que de métodos en la aplicación.

La idea de las pruebas unitarias es probar individualmente cada funcionamiento de la aplicación, y una vez que todas las pruebas hayan pasado, tener la seguridad que todo en la aplicación se encuentra bien. Por otro lado, si existe algún fallo en la aplicación, al tener las pruebas individualmente, será mucho más sencillo llegar al problema y resolverlo.

De esta manera las pruebas unitarias usadas y aplicadas de la manera correcta pueden asegurarse de que:

  • Los métodos estén funcionando de la manera correcta, aún tomando en cuenta los casos borde.
  • Los métodos y variables existan.
  • Los métodos y variables se puedan usar.
  • No existan errores de sintaxis.
  • El sistema cumpla con los requerimientos del cliente.

You don’t have a compiler. Your tests are your compiler. You must get 100% coverage, or you are shipping un-compiled code, and you are bad.

¿Que usar para hacer pruebas unitarias en Ruby?

Teniendo ya un contexto más claro de lo que son las pruebas unitarias y su importancia, podemos empezar a adentrarnos con algo más práctico.

Photo by Clark Tibbs on Unsplash

Para empezar a crear un código más completo y robusto incluyendo las pruebas unitarias, podemos usar Minitest. Es una gema que viene en el core de Ruby, y que nos proporciona un conjunto herramientas para realizar pruebas.

La forma para usar Minitest y empezar a hacer tus pruebas unitarias es la siguiente:

Se crea una clase que hereda de Minitest::Test en donde irán todas las pruebas de User. Y ahora, ¿como podemos probar código que ya existe?. Lo primero es crear una clase que contenga un método que queramos probar:

En este caso, estamos probando el método full_name de User. Lo primero que hacemos es el require del archivo donde se encuentra la clase User, dentro del archivo del test, luego se crea un método llamado test_full_name, en cual creará una instancia de User en el que se le pasan como parámetros “Manuel” y “Rodrigues”, y por último se hace el assert, que será el que verifica si el test pasa o no. Los test pueden pasar o no según los usos de assertions y expectations que se evalúen en los métodos.

El requiere ‘minitest/autorun' es la forma mas sencilla que nos proporciona Minitest para ejecutar las pruebas, simplemente escribiendo en la terminal:

Al ejecutarlo el output es el siguiente:

Pero al ejecutar el archivo ruby, ¿el autorun de minitest corre todos los métodos dentro de la clase UserTest? No, el autorun solo ejecutará los métodos que empiecen por “test_”, es decir, si dentro de esa clase existe algún otro método que no empiece de esa manera, no lo tomará en cuenta para la ejecución de los tests.

¿En que momento se deberían hacer los test?

Actualmente existe una tendencia en el mundo del desarrollo web, en donde las personas antes de desarrollar el código para la aplicación, se dedican a realizar las pruebas unitarias, de esta manera se pueden enfocar en conseguir los casos borde posibles, y al momento de desarrollar tienen las ideas más claras en cuanto al funcionamiento del método, permitiendo así un desarrollo más rápido y robusto.

Esta tendencia es un flujo de trabajo denominado TDD (Test Driven Development). La cobertura de pruebas con este flujo de trabajo tiende a ser de 90% a 100%. La secuencia para este flujo de trabajo es la siguiente:

  • Escribimos una prueba que cumpla con la funcionalidad esperada.
  • Ejecutamos la prueba. Esta debe fallar, en caso contrario es que no estamos desarrollándola bien, por lo tanto no es válida.
  • Se escribe la mínima cantidad de código necesaria para que el test pase.
  • Se vuelve a ejecutar la prueba, esta debe correr exitosamente.
  • Se recomienda refactorizar el código escrito, ya que cualquier cambio que hagamos vamos a estar seguros que nuestro código va funcionar si los tests son favorables.
  • Repetimos el punto uno para el siguiente requisito.

Esto se puede resumir en un ciclo llamado “Red, Green, Refactor”, que establece el ciclo del flujo de trabajo de TDD, en el que “Red” hace referencia a la prueba de la funcionalidad esperada, antes de desarrollar el método, “Green” hace referencia al desarrollo del método pasando así la prueba unitaria, y “Refactor” Hace referencia a arreglar el código luego de que la prueba unitaria pase.

--

--