5 consejos para escribir mejores test unitarios

Cuando empecé a escribir test unitarios cometí muchos errores y seguro que todavía cometo y cometeré muchos otros. En este artículo quiero ayudar a la gente que empieza a que no cometan los mismos o al menos a que puedan identificarlos.

1. Una razón para fallar

Cuando un test falla tiene que estar muy claro cual es la razón por la que ha fallado y si nuestro test unitario esta comprobando mas de una cosa, tendremos que mirar todas esas partes del código y eso nos va a costar mas tiempo de lo necesario.
Por el contrario, si solo comprueba una parte específica de nuestro código de producción, va a resultar trivial el solucionarlo cuando el test falle.
Como regla general, tener solo un assert, es la mejor forma de cumplir esta buena práctica.

2. Nombre del test

El nombre del test es muy importante, ya que al ejecutarlo lo primero que vas a ver cuando falle es el nombre. Así que, el nombre del test (junto con el mensaje de error) debe de decirte el porqué ha fallado sin tener que ver el código de producción.
El nombre tiene que contener el qué se está testeando y cual es el resultado que se espera. Como puedes imaginarte, al contener esta información el nombre del test no va a ser corto. Por lo que se podría decir que, al contrario que con el código de producción, el nombre va a ser largo.
En mi caso, utilizo el siguiente formato:

should_elResultadoEsperado_when_elCasoQueEstoyProbando

Un ejemplo del formato que utilizo seria el siguiente:

should_throw_exception_when_there_is_no_internet_connection

Hay mucha gente que en vez de utilizar un guión bajo para separar las palabras pone en mayúsculas la primera letra de la palabra:

shouldThrowExceptionWhenThereIsNoInternetConnection

No hay ninguna opción que sea la mejor. Utilizo guiones bajos porque personalmente entiendo mejor el texto.

3. Rápido

Que tus test unitarios se ejecuten en pocos milisegundos es una de las cualidades más importantes que deben tener.
Y te preguntarás el porqué es tan importante que tus test unitarios sean rápidos. Principalmente, porque podrás ejecutarlos cada pocos minutos y eso te permitirá el conocer si hay algo que no funciona como esperas, casi al momento de escribirlo.
El principal problema de velocidad en los test es debido a que el código habla con la base de datos, con el sistema de archivos o que acceden a internet.
Para solucionar este problema puedes utilizar dobles de test, en vez de la clase que realiza este tipo de operaciones que tardan tanto en ejecutarse.
Escribir dobles de test es fácil pero en general se suelen utilizar librerías que hacen el trabajo por ti y te dan más opciones. En Java tienes muchas. En mi caso, utilizo JMock.

4. Fixture

Ten mucho cuidado al compartir variables y métodos entre test. Más de una vez no entendía porque un test fallaba o porque un test no fallaba y la razón era porque tenía compartía variables entre varios test unitarios.
La mejor forma de evitar esto es no compartir variables entre test. También se pueden compartir variables, pero para evitar estos problemas, inicializa las variables compartidas en el método setUp de la clase.

5. Test que no comprueba nada

Cuando veas el código de tu test tiene que estar más que claro cual es la manera de que falle el test. Por eso, si tienes un test sin ningún assert y sin manejar las excepción, ¿como vas a saber cuál es la razón de que ha fallado?
Creo que todo test tiene que tener de forma explícita cual es su razón de fallar.
Así, un test que no comprueba el resultado, que no verifica que un objeto colaborador se ha llamado o que no maneja las excepciones no tiene mucho significado.