Escribiendo pruebas unitarias para código legacy

Desde que volví a trabajar en consultoría este es uno de los temas que más me he encontrado. Sinceramente no me sorprende pues:

  • TDD y la automatización de pruebas, son dos temas que están en claro ascenso de popularidad
  • Casi toda la bibliografía de TDD parte de la base de la creación de aplicaciones desde cero
  • Pero en una porción importante de casos, la gente ya cuenta con una aplicación, la cual muchas veces no ha sido diseñada de forma de facilitar su prueba

Casualmente ayer me crucé con un caso extremo. Resulta que hace un par de semanas dicté un workshop de TDD. Ayer me contactó uno de los asistentes para hacer una consulta de como encarar un caso concreto: tenia que agregar una funcionalidad a la una clase existente. La clase en cuestión tenia más de 3000 líneas de código. Si si, leiste bien, son tres ceros después del tres, o sea, tres mil líneas de código. El problema de una clase tan grande, es que resulta dificil que sea cohesiva. Se supone que pasar ser cohesiva, una clase debe hacer UNA cosa y hacer bien. Con tantas líneas, es muy posible que dicha clase esté haciendo demasiadas cosas.

Pero el problema que motivaba la consulta no eran las 3000 líneas de código, sino el constructor de dicha clase. Resulta que el constructor además de recibir varios parámetros, instanciaba un componente para conectarse a la base de datos. Eso impedia realizar una prueba unitaria de la clase, pues el solo hecho de instancialar implicaba conectarse a la base. Tampoco no habia chances de mockear la conexión pues era instanciada directamente dentro del constructor. ¿que hacer entonces?

Lo primero que uno intentaria es hacer un refactoring de la clase, pero dado que no existian pruebas de la misma, cualquier modificación implicaba un gran riesgo. Luego de analizar varias alternativas llegamos a una solución de compromiso, que nos permitiria escribir tests unitarios: agregar un constructor sin parámetros, que tenga la lógica para lanzar un excepción si era invocado en un ambiente distinto al de desarrollo/test. De esta forma podriamos instancias la clase en forma aislada en un ambiente de test y  aseguramos que no sea instanciada de esta forma en caso de estar en un ambiente distinto.

 

6 comentarios en “Escribiendo pruebas unitarias para código legacy

  1. Y si hacías un factory que realice la conexión, externo, que sea llamado en el contructor… ¿pero dentro de este factory se ‘sepa’ qué hacer en cada caso? no entiendo mucho qué es lo que estás haciendo, pero me suena una solució ‘saludable’.

    1. Si, seria claramente una posibilidad.
      Al mismo tiempo eso nos llevaria a otro debate conceptual: ese nuevo método debiera ser privado y los métodos privados no siempre pueden (stub/mock)earse.

      1. Por otro lado si vemos al constructor de una clase como un método más de dicha clase no veo ningún conflicto en que el método de inicialización sea público. De todas maneras hay que ver qué tecnología estás usando, ya que eventualmente se puede «hacer trampa» y acceder al método aunque sea privado 😉

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.