Hace tiempo, odiaba escribir test, me resultaban una perdida de tiempo. Y si empezaba a escribirlos, rápidamente los dejaba de lado porque me resultaban lentos.
Y el problema era que no sabía como escribir tests. Ahora me encanta escribir test, es más, me siento un poco incómodo si no tengo unos pocos tests para ver si todo está funcionando bien (al menos el «happy-path»).
Voy a contarte algunos trucos que me ayudan a la hora de escribir test, ¿compartes tu también los tuyos?

¿Por qué escribir tests?
Una de las cosas que más me ayudó a cambiar el chip fue cuando aprendía ver los aspectos positivos de los tests.
- Ayudan a reducir los bugs: Los test nos ayudan a cazar bugs y creo que esto es un beneficio secundario, los mejores beneficios vamos a contarlos a continuación.
- Eliminan el miedo: Si cambiamos una linea de código ¿estamos rompiendo algo? Sin test hacer refactor es complejo y nunca estamos seguros de si hemos cometido algún gazapo. Teniendo tests, al menos nos aseguramos que todo lo testeado sigue funcionando (si está bien testeado).
- Mejoran el diseño: Cuando tenemos test hacer refactorizaciones, extraer clases con código común, mover código de un sitio a otro,… es todo mucho más sencillo.
- Ganamos velocidad a largo plazo: Si el testing manual nos implica gastar mucho tiempo, repetir una y otra vez el mismo procedimiento… al final implementar nuevas funcionalidades es dificil. Y lo peor de todo es que hacer un cambio en una funcionalidad antigua implica volver a recordar como se hacía todo ese testing manual y repetirlo. Por lo que escribir tests, aunque sean pocos nos ayuda a ahorrarnos tiempo en repetir, repetir y repetir.
Estrategias
Ahora voy a contarte algunos trucos y estrategias que utilizo para escribir tests. No son la panacea, pero son «hacks» que me funcionan, espero que si ves como mejorarlas me dejes un comentario 😉
Escribe test mientras estas desarrollando
Escribir test después creo que esta bien, pero al final nunca se escriben porque no hay tiempo. A mi me gusta hacer Test Driven Development (TDD) y es una técnica que intento utilizar a menudo. TDD es una técnica que se basa en escribir los tests antes, en el blog ya he comentado un poco sobre esto aquí.
Escribir los tests primero, hace que me centre en un problema pequeño y trate de resolverlo de la manera más sencilla posible. Además escribir los tests antes, me hace analizar y «desgranar» en problemas pequeños que creo que puedo solucionar fácilmente.
Trata a tus tests como ciudadanos de primera clase
No tenemos que tratar a los tests como si fuesen «poco importantes», tenemos que hacer notar su importancia, no dejar test rotos, marcados como skipped y lo más importante, no debemos dejar de utilizarlos.
Recomiendo usar en los tests la mismas reglas que utilizamos en el código: – Eliminar la duplicación: creando factorías para «objetos dummmy» o lo que sea – Seguir las «style guidelines» del código: Si utilizas el estandar PSR-2, Symfony,… aplicalo en tu código. – Prioriza la legibilidad: Utiliza buenos nombres, intenta ser expresivo, utiliza el método «given/when/then» – Considera a los tests importantes en las code-reviews.
Si los tests son fáciles de entender, será mucho más fáciles arreglarlos si se rompen
Si es dificil escribir un test… eso es un code smell
Al principio cuando empiezas a escribir test, te sientes algo incómodo. A menudo, sientes que vas muy lento, que pierdes el tiempo escribiendo código que directamente no tiene que ver con la funcionalidad que te han pedido,.. nadie a dicho que el camino fuese fácil ¿o si?
Si encuentras que testear una clase es dificil, quizás sea porque no está del todo bien diseñada, eso puede ser un «code-smell». A mi me pasa, que cuando algo es difícil de testear es porque no estoy yendo por el buen camino. Echa un vistazo a esto
Haciendo tu código fácil de testestear, estás mejorando tu diseño.
Pon buenos nombres a tus tests
Si estas testeando la funcionalidad de hacer el «checkout de un carrito», seguramente tu test sea test_cart
¿no? Lo veo a menudo y a veces (intento que cada vez menos) lo hago, así que te sugiero que intentes reflejar en el nombre que es lo que esperas del test. Quizás algo así test_cart_value_cannot_be_negative
.
Creo que es lo más difícil de todo, encontrar buenos nombres es muy difícil, ya hemos hablado de eso antes
Tener buenos nombres en los tests te ayuda a saber por donde vas, que llevas hecho y que te falta. Con test_cart
es difícil saber más test necesitas.
Usa solo un assertion por test
Los test se empiezan a emborronar cuando se ponen demasiados assertion. A veces tiene sentido tener varios assert, pero intenta mantenerlos al mínimo.
Varios assert hacen que sea difícil saber a simple vista que se está probrando y peor aún cuando una funcionalidad cambio y tienes el mismo assert repartido en varios tests.
Mantén tus tests pequeños
Si puedes mantener tus tests pequeños y cortos es buenísimo. Tener grandes setup, muchas clases implicadas, empieza a oler a un diseño demasiado complejo.
Errores comunes
Voy a a hablarte de los errores que he comentado y que intento no cometer cuando hago tests
Mocks
Los «mocks» te ayudan a simular la interacción cuando necesitas que la clase interaccione con otros módulos/sistemas. Yo utilizo mocks para reemplazar dependencias de servicios externos en los tests.
Los mocks pueden hacer que tus tests se vuelvan complicados, difíciles de leer o que pierdas demasiado tiempo viendo porque falla un mock cuando «no debería», o aun peor que los mocks nos den un falso positivo cuando no deberían.
Los mocks son útiles tan pronto como entendemos sus limitaciones y trade-offs.
Metodos helper gigantes
Escribir helper te ayuda a mantener el código de los tests pequeño y entendible. Sin embargo, hay que valorar cuanto cuesta mantenerlos y si al cambiar un helper tienes que modificar demasiados tests.
Sin embargo, los métodos auxiliares pueden hacer los tests difíciles de entender, sobre todos si tienes asserts dentro de los helpers.
He visto métodos helper que necesitan 10 argumentos de entrada y con if anidados… si los métodos helpers son tan grandes, se hacen difíciles de depurar cuando algo va mal. Y lo peor de todo, es que es en lo último que te fijas, siempre piensas, que el error está en el código cuando pude ser el helper el que esté molestando.
Test Lentos
Mantener los tests pequeños y rápidos. Cuanto más rápidos sean los tests más probable es que los ejecutes más veces. Si una suite de test se vuelve lento, al final te dará pereza ejecutarlos,y nadie realizará tests.
Optimizar de vez en cuando los tests para aminorar el tiempo de ejecución hace que se elimine esa «pereza» por ejecutarlos.
Si una suite de test dura 8 minutos, ¿de verdad crees que vas a ejecutarla a menudo? Lo dudo. Muchas veces el problema no está en los tests en sí, sino en el setup que es muy costoso y se ejecuta muchas veces, por ello tienes que tener en cuenta todos los «templates» disponibles para mover las inicializaciones donde más te convenga.
TemplateMethodsTest::setUpBeforeClass
TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testOne
TemplateMethodsTest::assertPostConditions
TemplateMethodsTest::tearDown
.
TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testTwo
TemplateMethodsTest::tearDown
TemplateMethodsTest::onNotSuccessfulTest
F
TemplateMethodsTest::tearDownAfterClass
Cuanto más rápido se ejecuten las pruebas, más valor vas a sentir que te aportan.
Conclusiones
Me encanta escribir tests. Los test acaban transformando nuestra manera de pensar y de escribir código. Creo que aplicando estas estrategias escribir test se hace más sencillo, nos da menos pereza y al final acabamos cogiendo cariño a los tests.
Algunos libros recomendables para escribir mejores test y donde explicaran consejos 1000 veces mejores que estos son:
Un comentario en “Estrategias para escribir mejores test”